5 Replies Latest reply on Jan 14, 2015 6:08 AM by OliverKeller

    why is pin muxing on Gen 1 slower since update to 1.0.4?

    OliverKeller

      I developed Arduino code that sends DMX protocol packets over Serial1 (connected to a Rs-486 line driver shield) on the Galileo Gen 1 board.

      The DMX standard sends serial data at a rate of 250.000 bit/s with 8n2 format (two stop bits). Before each DMX frame, a break signal must be send, which should be at least a 88us long low level on the line. To achieve this with low delay as possible, I multiplex between the pin 1 mode being configured as output and as serial1 port.

      The Arduino setup() routine contains this:

       

      //set low level as default on serial pin for break frame
      pinMode(1, OUTPUT);
      digitalWrite(1, LOW);
      //mux pin 1 to serial mode with DMX speed and 8n2 data format (idle level is high)
      Serial1.begin(250000);
      
      
      
      
      

       

      The in the loop() routine, using the previous Arduino Intel IDE release, the following two statements created a break gap (low level) of about 5.5 ms on pin 1:

        muxSelectDigitalPin(1);
        muxSelectUart(1);
      
      
      
      
      

       

      Now, since I updated to Arduino-1.5.3-Intel-1.0.4, the low level break gap increased by factor of 8 to about 45 ms! This is not acceptable anymore, because the break gap is now almost twice as large as the DMX data fame itself, so the effective DMX update rate gets very slow.

      Note, with the new IDE version I had to exchange muxSelectDigitalPin(1) with muxSelect(1, FN_GPIO_OUTPUT), because the former function disappeared. But I believe this is not the source of the problem.

       

      Do you have any explanation for the extended pin multiplexing times?

      Could I improve it by changing something in the Arduino x86 core? I noticed a lot has changed in the core code between the two IDE releases.

       

      For the reference, I modified the Arduino Intel core to be able to send Serial data at 250.000 bit/s with 8n2 format. It can be found here:

      added custom baud rate of 250000 bps ·  bec93b9 · ozel/arduino-cores · GitHub

       

      Sending a whole DMX frame from an Arduino sketch on the Galileo looks currently like this:

        // generate DMX break gap
        muxSelect(1, FN_GPIO_OUTPUT);
        muxSelectUart(1);
      
        // send empty data: START CODE
        Serial1.write((uint8_t)0);
      
        // write all the channel values from the DMX array
        Serial1.write(DMXBuffer, sizeof(DMXBuffer));
      
      
      

       

      For further details on DMX please see this nice technical summary: DMX512 | Erwin Rol Software Engineering

        • 1. Re: why is pin muxing on Gen 1 slower since update to 1.0.4?
          CMata_Intel

          Hi OliverKeller

           

          What is the purpose of muxSelectDigitalPin and muxSelectUart? It's only used  in order to set the parameters in the serial communication? Or are essential in your code? You also could set the parameters with these commands:

          ttyS0 is the port in the Digital pins (0 and 1).

           

          void setup(){

          system("stty -F /dev/ttyS0 250000");

          system("stty -F /dev/ttyS0 cs8");

          system("stty -F /dev/ttyS0 cstopb");

          }

          • 2. Re: why is pin muxing on Gen 1 slower since update to 1.0.4?
            OliverKeller

            Hi CMata_Intel,

             

            I toggle between digital output and UART pin modes to achieve the DMX specific "SAPCE for BREAK" signal as listed in the DMX512 link above, which should be a low level pulse on the TX pin of at least 88 us.

            The problem is that with version 1.0.4, this pin multiplexing takes much longer than before, 5.5 ms vs. 45 ms.

             

            In principle the break signal could be faked by switching to a lower baud rate and then sending a zero byte.

            But switching between different rates via consecutive serial1.begin() call takes even longer, creating huge unnecessary gaps between two DMX frames.

            After all the DMX protocol spec allows an update rate (= frame rate) of around 40 Hz, but only if the break pulses are not significantly longer than required.

             

            Setting 250000 via stty didn't work. However I tested it in the shell with using the "setserial" command and its "custom divisor" option which does under the hood the same as my Arduino x86 core modification above. There was some problem, which I don't remember now, where setting all this from multiple system() calls was not appropriate.

            • 3. Re: why is pin muxing on Gen 1 slower since update to 1.0.4?
              OliverKeller

              I found a small work around, setting the gpio multiplexer from the linux terminal to regular pin mode and back to UART:

                system("echo 1 > /sys/class/gpio/gpio41/value && echo 0 > /sys/class/gpio/gpio41/value");
              
              

              This gives a low level break gap of under 3 ms, which is fine and even faster than using the mux* functions of the Arduino API before.

               

              However, as soon as I put the two commands in separate system() calls, it takes a bit above 10 ms.

              So I suspect that, instead of the API internals, maybe the compiler settings for Arduino sketches have be changed since Verison 1.0.4. in the Intel Arduino IDE!

              Are debug symbols maybe now activated? Has the optimisation level been changed?

               

              For the records, it is possible to set the serial1 to 251345 baud (almost 250k, well enough within DMX spec limits) with the following setup() config:

                // set custom divisor 11 to get 251345 baud:
                system("setserial /dev/ttyS0 spd_cust");
                system("setserial /dev/ttyS0 divisor 11");
                Serial1.begin(38400);  //this virtual rate setting of 38400 only tells the system to respect the custom baud rate set above
                system("stty -F /dev/ttyS0 cstopb");  //enable 2 stop bits
              
              

               

              This works if the Baud_base is set too 2764800 (2764800 / 11 = 251345). It can be verified with "setserial -a /dev/ttyS0".

              Now I remember, I added DMX baud rate configuration to the x86 Arduino core (available on github link above) to be independent of the base baud rate. Parsing the current base baud rate from the output of the setserial command would be too ugly inside the Arduino sketch IMHO. That's why I added code in the core to set the rate as close as possible to 250k depending on the actual base rate value.

               

              Can it be assumed that all Intel Galileo boards will always be shipped with the same base baud rate of 2764800? Is it maybe a 16550A UART specific thing of the Quark, which can't be changed anyways? (calling e.g. "setserial /dev/ttyS0 Baud_base 3000000" fails)

               

              If anyone wants a complete example sketch on how to send DMX packets on the Galileo equipped with a RS-485 driver shield I can provide it.

              But it seems there is not much interest. My posts here contain all relevant details, though.

              • 4. Re: why is pin muxing on Gen 1 slower since update to 1.0.4?
                CMata_Intel

                Hi OliverKeller

                 

                Take a look at the Quark Datasheet.You will see that it supports baud rates between 300 and 2764800.

                I encourage you to upload your sketch, in the Galileo Projects you will find a way to upload your code and you also could attach some pictures of your configuration.

                 

                Regards;

                CMata

                • 5. Re: why is pin muxing on Gen 1 slower since update to 1.0.4?
                  OliverKeller

                  CMata_Intel, of course a lot of baud rates can be set (and thanks for the link to the manual never the less), but the one I need for DMX - something close to 250k - can't be set straight forward, as it is not a standard baud rate. Is is also not a standard baud rate on most *nix systems. Just test the commands you proposed! "stty -F /dev/ttyS0 250000" doesn't work, because it is not a standard baud rate, the error is "stty: invalid argument '250000'".

                  If you are curious, arduino-cores/TTYUART.cpp at master · ozel/arduino-cores · GitHub, defines all the supported baud rates. Which is why I started changing the code there, as an alternative to mess with setserial and stty calls on the command line.


                  I might publish an example sketch as a project. But as I wrote, the relevant code lines I used to create valid DMX packets are all documented above.