Use a rs485 communication module

Posted on
Page
of 2
/ 2
Next
  • Hello,

    I've worked/played with a flipdot display from alfazeta (7x7 dots) with an arduino. The display is driven by an rs485 protocole and specific ordered bits...
    I would like to use an espruino to do it again.
    On arduino we use a software serial
    I've read that there is no software serial on espruino
    Do i have to use the serial module on specific pin or it is not possible... Not sure to understand?

    The display use a specific ordered bit sentence compose with 3 bits for command, x bits for data display (depend of size), and an end bit.

    Is there an example somewhere to start coding?

    Regards

    éric

  • Hi, those displays are awesome! If you don't mind me asking, how much did your 7x7 one cost?

    Normal 'hardware' serial has to output on specific pins on the Original/Pico/WiFi boards (for instance look for USARTx_TX pins on http://www.espruino.com/Pico#pinout). On Puck.js it can be any pin.

    However, it sounds like hardware serial won't do as you're limited to 7 or 8 bits.

    Instead, you can easily use digitalPulse to send out a series of pulses. What's the baud rate of the data you're sending?

    You could do something a bit like this pretty easily:

    function toPulses(line, baud) {
      pulses = [];
      // stop bit
      line+="0";
      // start bit
      var lastBit = false; // start bit
      var time = 1;
      for (var x in line) {    
        var bit = line[x]!="0";
        if (bit!=lastBit) {
          pulses.push(time/baud);
          time = 0;
          lastBit = bit;
        }
        time++;
      }
      if (!lastBit)
        pulses.push(time/baud);
      return pulses;
    }
    
    var p = toPulses("1001010101010001", 9600/*baud rate*/);
    digitalPulse(pin, 0, p);
    

    So then all you need to do is set up the string you give to toPulses - start/stop bits are added automatically so you just need your 3 bits of command + x bits of data.

  • @Gordon, the 7x7 display is around 80€ wo VAT + 23€ for shipping to France + paypal fee
    there is an USB version for 5€ more.

    the baud rate is 9600 or 19200, 38400, 57600 (physical dipswitch on the board)
    there is no fonts for the display, it's just a screen, you have to draw your font and convert char to bits

    by ex.
    Send all white dots to all connected panels (address 0xFF) and turn dots as soon as data is received.

    0x80 0x87 0xFF 0x7F 0x7F 0x7F 0x7F 0x7F 0x7F 0x7F 0x8F
    

    0x80: header
    0x87: command (show)
    0xff: address (panel)
    7 * 0x7f: display data "b01111111"
    0x8f: end char

    therefor your exemple need to be converted from hex value to 0/1.
    is it good way?

    parseInt(num, baseFrom).toString(baseTo);
    

    regards

    é.

  • Thanks! A bit pricey, but tempting :)

    Yes, what you're doing is fine - but you also need to watch out for parseInt dropping the initial zeros!

    I'd just rewrite it as an array:

    code = [0x80,0x87,0xFF,0x7F,0x7F,0x7F,0x7F,0x7F­,0x7F,0x7F,0x8F];
    
    Then you can convert it with:
    
    code.map(x=>((x+256).toString(2)).substr­(1)).join("")
    

    However, with 8 bits even when you're controlling the 7 bit flip dots, are you sure it's not normal serial data? eg, with one start & stop bit per byte? It seems like the most likely option by far.

    Do you have a link to the Arduino code?

    Also, Espruino does have its own graphics library & fonts in that'd be easy to use for stuff like this: https://www.espruino.com/Graphics

  • i do not put it online, for share (i'm lazy guy), i give it here...
    the code is a bit confuse... it show all the alphabet char...
    but draws a transition between chars (line by line with 20ms between each frame)...
    but sure the code is working and draws chars on flipdot :)

    [#include](http://forum.espruino.com/sea­rch/?q=%23include) <SoftwareSerial.h>
    
    int compteurG = 0;
    int compteur = 0;
    int a = 0;
    int ncar = 27;
    boolean drapo = false;
    byte lettreA[7], lettreB[7];
    
    // assemble message
    byte msg [11] = {
      0x80,    // start byte
      0x87,    // send byte and refresh
      0xFF,    // to all display adress
      0x01,    // first data thingy to display, is non printable ASCII
      0x01,
      0x01,
      0x01,
      0x01,
      0x01,
      0x01,
      0x8F     // end byte
    };
    
    byte charSet[][7] = {
      {0x0, 0x0, 0x18, 0x14, 0x14, 0x2e, 0x0},
    {0x8, 0x14, 0x14, 0xc, 0x34, 0xa, 0x0},
    {0x0, 0x0, 0x18, 0x4, 0x4, 0x3a, 0x0},
    {0x8, 0x8, 0x8, 0xc, 0xa, 0x1c, 0x0},
    {0x0, 0x0, 0x18, 0x1c, 0x4, 0x1a, 0x0},
    {0x10, 0x28, 0x18, 0x8, 0xc, 0xa, 0x4},
    {0x18, 0x1c, 0x10, 0x38, 0x14, 0x14, 0x8},
    {0x8, 0x14, 0x14, 0xc, 0x14, 0x32, 0x0},
    {0x8, 0x0, 0x8, 0x8, 0xc, 0x32, 0x0},
    {0x8, 0x0, 0xc, 0x8, 0x18, 0xc, 0xc},
    {0x0, 0x24, 0x14, 0xc, 0x14, 0x22, 0x0},
    {0x8, 0x14, 0x14, 0x14, 0x8, 0x34, 0x0},
    {0x0, 0x0, 0x0, 0x34, 0x2a, 0x2a, 0x0},
    {0x0, 0x0, 0x0, 0x18, 0x14, 0x36, 0x0},
    {0x0, 0x0, 0x58, 0x34, 0x24, 0x1a, 0x0},
    {0x0, 0x0, 0x1c, 0x14, 0x1e, 0x24, 0x4},
    {0x0, 0x0, 0x1c, 0x14, 0x3c, 0x12, 0x10},
    {0x0, 0x0, 0x1c, 0xc, 0xc, 0x37, 0x0},
    {0x0, 0x0, 0x8, 0x14, 0x12, 0x2c, 0x0},
    {0x8, 0x3c, 0x8, 0x8, 0x8, 0x34, 0x0},
    {0x0, 0x0, 0x0, 0x14, 0x14, 0x1e, 0x0},
    {0x0, 0x0, 0x0, 0x34, 0x14, 0xa, 0x0},
    {0x0, 0x0, 0x2a, 0x2a, 0x2a, 0x15, 0x0},
    {0x0, 0x0, 0x14, 0x8, 0x14, 0x22, 0x0},
    {0x0, 0xa, 0xa, 0xc, 0xc, 0xa, 0x4},
    {0x0, 0x0, 0x3c, 0x10, 0x8, 0x3c, 0x0},
      {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}
    };
    
    [#define](http://forum.espruino.com/sear­ch/?q=%23define) TX_ENABLE_PIN 3            // define the EIA-485 transmit driver pin
    [#define](http://forum.espruino.com/sear­ch/?q=%23define) LED_PIN 13
    
    // SoftwareSerial rs485(RO, DI);
    SoftwareSerial rs485(4, 2); // pins on rs485 module ->
    
    void setup() {
      pinMode(TX_ENABLE_PIN, OUTPUT);  // driver output enable
      rs485.begin (19200);              // vitesse com
      Serial.begin(9600);
      pinMode(LED_PIN, OUTPUT);
      // si pas de print softwareSerial ne fonctionne pas
      Serial.println("7x7 flipdots from Alfazeta");
    }
    
    void loop() {
      digitalWrite (TX_ENABLE_PIN, HIGH);     // enable transmit driver
      digitalWrite (LED_PIN, HIGH);
      
      // change les lettres tous les 7 tours
      // remplit les buffers de lettre pour anim de transition de caractère
      if (compteurG%7 == 0) {
        for (int i=0;i<7;i++){
          lettreA[i] = charSet[compteur%ncar][i];     // caractère avant
          lettreB[i] = charSet[(compteur+1)%ncar][i]; // caractère après
        }
        compteur++; // compteur du caractère à afficher dans charSet
      }
      
      for (int i = 3; i <= a%7+3; i++) { // nbr bits trame
        msg[i] = lettreB[i-3];
      }
      for (int i = a%7+4; i < 10; i++) { // nbr bits trame
        msg[i] = lettreA[i-3];
      }
      // envoie la séquence msg[] à l'afficheur
      for (int i = 0; i < 11; i++) {
        rs485.write(msg[i]);                // flip display print
        //Serial.print(msg[i],HEX);
        //Serial.print(" ");
      }
      //Serial.println();
      
      // gestion du buffer
      while (!(UCSR0A & (1 << UDRE0)))  // Wait for empty transmit buffer
        UCSR0A |= 1 << TXC0;  // mark transmission not complete
      while (!(UCSR0A & (1 << TXC0)));   // Wait for the transmission to complete
    
      digitalWrite(TX_ENABLE_PIN, LOW);       // disable transmit driver
      digitalWrite(LED_PIN, LOW);
    
      if (compteurG % 7 == 0) {
        // si lettre affichée au complet
        delay(700);
      } else {
        // si en cours de transition de lettre
        delay(20);
      }
    
      if (compteurG >= 7) { compteurG = 0; } else { compteurG ++;}
      if (a >= 7) { a = 0; } else { a ++;}
      if (compteur > ncar) { compteur = 0;}
    }
    
  • Good enough :)

    Ok, it looks like you don't need anything fancy at all. Just use the standard hardware serial.

    • Find a USARTx_TX pin on your board's pinout page (linked from here): http://www.espruino.com/Reference#boards­
    • If it was USART1, do something like:

      Serial1.setup(19200,{tx:TX_ENABLE_PIN});­
      
      function sendData(data) {
      digitalPulse(TX_ENABLE_PIN,1, (data.length+1)*10/19200);
      Serial1.write(data);
        
      }
      
      sendData([0x80,0x87,0xFF,0x7F,0x7F,0x7F,­0x7F,0x7F,0x7F,0x7F,0x8F]);
      

    That should all work ok - it's a bit fiddly because you have to set the TX enable pin on RS485, but not the end of the world.

  • Sorry it does not work
    there is no callback on serial therefor you pulse on the TX_ENABLE_PIN ok.
    but initiate the serial with the TX pin ...
    i've tried this

    var TX_ENABLE_PIN = A8;
    var TX_PIN = B6;
    
    function sendData(data) {
    	digitalPulse(TX_ENABLE_PIN,1, (data.length+1)*10/19200);
    	Serial1.write(data);
    	console.log("envoie data", data.toString());
    }
    
    function onInit() {
    	Serial1.setup(19200,{tx:TX_PIN});
    	setInterval(sendData, 2000, [0x80,0x87,0xFF,0x01,0x01,0x01,0x01,0x7F­,0x7F,0x7F,0x8F]);
    }
    

    is it good or i can't use serial1 with usb plugged?

  • Serial1 should work fine with USB plugged in.

    It'll stop working when USB is unplugged, and you just need to add USB.setConsole(1) to onInit to fix that (by forcing the JS console to stay on USB even if USB is unplugged).

    So you have an oscilloscope or any way to debug this? It is possible that the delay of JS execution is longer than the time we allow in the digitalPulse.

    You could try digitalPulse(TX_ENABLE_PIN,1, 2+(data.length*10/19200)); instead?

  • No oscilloscope :(
    i've tried with low baudrate: idem

  • Have you tried with low baudrate, with the baud rate changed in digitalPulse as well?

    Also, maybe just try removing digitalPulse and setting TX_ENABLE_PIN constantly with digitalWrite(TX_ENABLE_PIN,1) (you could try digitalWrite(TX_ENABLE_PIN,0) just in case it was inverted)

  • Ok it works, i've used your idea and tried with other value.
    For 9600 baud, i've added 13
    For 19200 baud, 7

    I'll try with a pin in high

  • Thanks very much @Gordon

    I've use the digitalWrite(TX_ENABLE_PIN, 1)
    With higher than 9600 baud rate, some frame are lost and display do not completely refresh.
    It does not occur at 9600.

    Alfazeta display are compatible with espruino👏🏼🎉 and with a simple way...
    I love simple things.

  • Great! Now you need to try:

    var g = Graphics.createArrayBuffer(8,7,1);
    g.drawLine(0,0,7,7);
    Serial1.write([0x80,0x87,0xFF],g.buffer,­[0x8F]);
    

    You can even use stuff like g.drawString("Hello",x,y), and you can change rotation with g.setRotation(1) (2, or 3).

    (I made the graphics 8px x 7px so that each row/column aligns properly)

  • i create a post in project category
    http://forum.espruino.com/conversations/­306572/

  • Thanks! That's great!

    I've always liked those displays, but have never been able to justify getting any. It's nice to see they're actually really easy to interface to.

  • Hello @Gordon
    i continue to experiment with flipdot display.
    i'm enable to use a higher baudrate than 9600 otherwise i'm lossing some frame.
    I've tested the serial port voltage on serial1 it is around 3.3v... is it enough to use with the rs485 communication module? do i need a level shifter?

    second question is about setinterval sending data.
    If i reduce interval there is a limit around 350 or 400 ms between each sending. can't do quicker... have you any idea about the problem? does it come from the board or from the display?

    thanks

  • I think RS485 adaptors should be fine at 3.3v. I've definitely used them in the past without problems. Sometimes you need terminating resistors on RS485 itself though?

    Sending the actual data should take ~12ms at 9600 baud, so there's lots of leeway (for 60fps or so!). About the only thing I can think of is that the display itself looks for TX_ENABLE_PIN to go low or waits for ~350ms. So you could try experimenting with ways to control TX_ENABLE_PIN?

    Having said that, have you seen thess displays updating any faster than every ~400ms? I can totally imagine they're just not designed for fast updates.

    The video on the internet using a massive display to show video said something about them using custom controllers for faster updates - so presumably that was because the standard controllers just don't do the high speeds?

  • I've tried with the digitalPulse()'s way without noticiable difference.

  • hello @Gordon,
    I've found the delay's responsible:

    g.setFontDennis8();
    

    if i put in comment, the frame rate is good...
    have you a way to keep the framerate good?
    the default font is too small and with no accents.

    regards

  • That's really strange... and you're using up to date firmware?

    On a 7x7 graphics canvas it should be almost instant.

    Could you post up a bit of code as an example that shows the slowdown, without the RS485?

    For example:

    
    var g = Graphics.createArrayBuffer(8,7,1);
    var t;
    t = getTime();
    g.drawString("Hello");
    console.log("Draw took ",getTime()-t);
    
    t = getTime();
    g.setFontDennis8();
    g.drawString("Hello");
    console.log("Draw took ",getTime()-t);
    
  • var TX_ENABLE_PIN = A8;
    var TX_PIN = B6;
    var compteur=0;
    var balance = 1;
    
    var g = Graphics.createArrayBuffer(8,7,1);
    
    var texte = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed pellentesque dui at leo consectetur, finibus tempor tellus sollicitudin. Maecenas dignissim est sem, feugiat mollis sem aliquet a. Sed nunc ex, faucibus dapibus tortor et, dignissim tincidunt nisl. Nulla facilisi. Maecenas nunc nunc, interdum eu vulputate id, laoreet a lacus. Sed et felis dapibus sapien porta euismod vel ut mi. Etiam at augue vel quam dictum sodales a et purus. Donec ac erat posuere, maximus erat sit amet, facilisis lacus. Aenean dictum, sem et dignissim sagittis, eros velit ultrices purus, nec lobortis risus elit sed lectus. Maecenas tincidunt convallis mauris sit amet scelerisque. Suspendisse et lorem sit amet ligula dignissim feugiat. Maecenas tincidunt, eros non ultricies tincidunt, risus magna laoreet urna, in ultrices mi ipsum eget metus. Nam mollis ultricies fermentum. Fusce ac molestie mi, non suscipit quam. Nunc sit amet facilisis diam. Donec erat tellus, pellentesque vitae erat eget, viverra rutrum ex. Proin rhoncus nisl quam, a sodales nibh vulputate molestie. Proin at ex dolor. Cras turpis lacus, volutpat ut purus et, volutpat luctus massa. Mauris vel diam vestibulum, gravida risus sit amet, tristique ante. Mauris imperdiet lobortis arcu, in sollicitudin sem malesuada at. Donec volutpat justo quam, non viverra nulla ultrices quis. Duis luctus, turpis nec faucibus consequat, augue sapien consectetur ex, sit amet rhoncus ante purus in purus. In tristique dui nisl, ac fermentum turpis dictum et. Cras eu rutrum neque. Donec tempus tincidunt justo, quis elementum ex cursus eu. In lobortis, velit at tempor fringilla, ante risus feugiat dolor, eget eleifend nulla nibh eu urna. Nam quis sodales tortor, vitae convallis nisl. Suspendisse at accumsan ipsum, vel semper sapien. Sed sit amet sem dignissim, ultricies justo eget, euismod metus. Donec condimentum molestie velit, a sagittis turpis luctus vitae. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Duis id fermentum neque. Fusce euismod tristique urna at molestie. Maecenas eget facilisis magna, et euismod tellus. Nulla lacus nulla, cursus gravida libero vel, ultrices pharetra lacus. Vivamus sagittis ante leo, sed ultrices purus vestibulum at. Fusce aliquam blandit arcu, nec sodales diam interdum vel. Phasellus eget felis vitae elit vehicula porta ut eu sapien. Morbi congue eu dui vel posuere. Quisque sit amet mattis diam, porttitor porta nibh. Etiam id dictum ligula, a viverra fusce.";
    
    function sendData() {
      if (compteur < -g.stringWidth(texte))
        compteur = 7;
      g = Graphics.createArrayBuffer(8,7,1);
      //g.setFontDennis8();
      g.drawString(texte,compteur,0);
      balance = !balance;
      digitalWrite(LED1, balance);
      digitalPulse(TX_ENABLE_PIN,1,7);
      Serial1.write([0x80,0x87,0xFF],g.buffer,­[0x8F]);
      compteur--;
    }
    
    function onInit() {
      require("FontDennis8").add(Graphics);
      Serial1.setup(19200,{tx:TX_PIN});
      setInterval(sendData, 100);
    }
    

    just try this un/comment the setFontDennis8()
    the blinking is slowing down...

    my texte var is about 2500 char long...

    regards

  • do i need to troncate the texte by smaller unit? is it the conversion to bitmap that is time consuming?

  • @Gordon
    with setFontDennis();
    0,234

    without setFontDennis();
    0,0223

    :/

  • Aha! Yes, drawing a small novel on to your 7x7 LCD screen would definitely slow things down :)

    It is the actual drawing of the characters to the bitmap that takes a while - I don't believe I ever skipped drawing characters if they were offscreen, because I thought that would be quite rare.

    To speed it up, I'd try and split it into smaller chunks. To be honest even calling stringWidth on that amount of characters each frame will be making things slightly slower than they need to be.

    OR I just fixed it, so if you use one of the cutting edge build at http://www.espruino.com/binaries/travis/­2cdc51943388fe3d1944936bf02ad7fae9e0258c­ it'll be a lot faster.

  • @Gordon, with that code there is a slowing down of the frame rate with/without the setFontDennis8() (the time i've gave you, was resulting of the code above with commented or not the font call...) just that...
    Using custom font is 10 time slower.. why?

    how to reduce the delay?
    if i reduce the design of char (if i remove unused char design with white pixels...)will it be less time consuming for setting the font?

    in other way why your custom font is quicker use than an external font?
    Is it because the font is smaller (4x3 or 5x4)?
    is it possible to produce a custom firmware with a custom font embeded with accent (yes i'm french and i use accents like many other non-english writers :) )

    regards

    var TX_ENABLE_PIN = A8;
    var TX_PIN = B6;
    var compteur=0;
    var longT = 0;
    
    var g = Graphics.createArrayBuffer(8,7,1);
    
    var texte = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed pellentesque dui at leo consectetur, finibus tempor tellus sollicitudin. Maecenas dignissim est sem, feugiat mollis sem aliquet a. Sed nunc ex, faucibus dapibus tortor et, dignissim tincidunt nisl. Nulla facilisi. Maecenas nunc nunc, interdum eu vulputate id, laoreet a lacus. Sed et felis dapibus sapien porta euismod vel ut mi. Etiam at augue vel quam dictum sodales a et purus. Donec ac erat posuere, maximus erat sit amet, facilisis lacus. Aenean dictum, sem et dignissim sagittis, eros velit ultrices purus, nec lobortis risus elit sed lectus. Maecenas tincidunt convallis mauris sit amet scelerisque. Suspendisse et lorem sit amet ligula dignissim feugiat. Maecenas tincidunt, eros non ultricies tincidunt, risus magna laoreet urna, in ultrices mi ipsum eget metus. Nam mollis ultricies fermentum. Fusce ac molestie mi, non suscipit quam. Nunc sit amet facilisis diam. Donec erat tellus, pellentesque vitae erat eget, viverra rutrum ex. Proin rhoncus nisl quam, a sodales nibh vulputate molestie. Proin at ex dolor. Cras turpis lacus, volutpat ut purus et, volutpat luctus massa. Mauris vel diam vestibulum, gravida risus sit amet, tristique ante. Mauris imperdiet lobortis arcu, in sollicitudin sem malesuada at. Donec volutpat justo quam, non viverra nulla ultrices quis. Duis luctus, turpis nec faucibus consequat, augue sapien consectetur ex, sit amet rhoncus ante purus in purus. In tristique dui nisl, ac fermentum turpis dictum et. Cras eu rutrum neque. Donec tempus tincidunt justo, quis elementum ex cursus eu. In lobortis, velit at tempor fringilla, ante risus feugiat dolor, eget eleifend nulla nibh eu urna. Nam quis sodales tortor, vitae convallis nisl. Suspendisse at accumsan ipsum, vel semper sapien. Sed sit amet sem dignissim, ultricies justo eget, euismod metus. Donec condimentum molestie velit, a sagittis turpis luctus vitae. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Duis id fermentum neque. Fusce euismod tristique urna at molestie. Maecenas eget facilisis magna, et euismod tellus. Nulla lacus nulla, cursus gravida libero vel, ultrices pharetra lacus. Vivamus sagittis ante leo, sed ultrices purus vestibulum at. Fusce aliquam blandit arcu, nec sodales diam interdum vel. Phasellus eget felis vitae elit vehicula porta ut eu sapien. Morbi congue eu dui vel posuere. Quisque sit amet mattis diam, porttitor porta nibh. Etiam id dictum ligula, a viverra fusce.";
    
    function sendData() {
      if (longT === 0) {
        longT = g.stringWidth(texte);
        console.log(longT);
      }
      if (compteur < -longT)
        compteur = 7;
      g = Graphics.createArrayBuffer(8,7,1);
      t = getTime();
      g.setFontDennis8();
      g.drawString(texte,compteur,0);
      console.log("Draw took ",getTime()-t);
      LED1.toggle();
      digitalPulse(TX_ENABLE_PIN,1,7);
      Serial1.write([0x80,0x87,0xFF],g.buffer,­[0x8F]);
      compteur--;
    }
    
    function onInit() {
      require("FontDennis8").add(Graphics);
      g.setFontDennis8();
      Serial1.setup(19200,{tx:TX_PIN});
      setInterval(sendData, 70);
    }
    

    ps: i define only one time (in this code) the stringWidth() ;) thxs for the advice.

    ps:2 with shorter text, it's quicker but not that much.

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

Use a rs485 communication module

Posted by Avatar for Mrbbp @Mrbbp

Actions