Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 9 of 9

Thread: Serial Monitor speed question

  1. #1

    Serial Monitor speed question

    Hello,

    I have the following program running on an Arduino Mega 2560 that i'd like to move over to a Teensy. The problem I am having is that when I run it on the Teensy, it cuts the first digit off from the result and the response rate in the serial monitor changes to about once every second. As a side note, I know the teensy has the transmitterEnable() functionality and I was wondering if I could get help implementing that here instead of the preTransmission/postTransmission functions. Thanks in advance.

    Code:
    #include <ModbusMaster.h>
    
    #define MAX485_DE 2 //Enable transmit pin for MAX485 (both RE/DE tied together)
    
    // instantiate ModbusMaster object
    ModbusMaster node;
    
    void preTransmission()
    {
      digitalWrite(MAX485_DE, 1);
    }
    
    void postTransmission()
    {
      digitalWrite(MAX485_DE, 0);
    }
    
    void setup()
    {
      pinMode(MAX485_DE, OUTPUT);
    
      digitalWrite(MAX485_DE, 0);
    
      // Baudrate for serial monitor if you want to see responses
      while (!Serial);
      Serial.begin(38400);
    
      //Baudrate of modbus device is 38400
      while (!Serial1);
      Serial1.begin(38400);
    
      // Modbus slave ID is 9 and MAX485 is connected to RX1/TX1
      node.begin(9, Serial1);
      // Callbacks allow us to configure the RS485 transceiver correctly
      node.preTransmission(preTransmission);
      node.postTransmission(postTransmission);
    }
    
    void loop()
    {
      uint8_t result;
      //Need data from starting address 0x41 with length 2
      result = node.readHoldingRegisters(0x41, 2);
    
      Serial.println(node.getResponseBuffer(0x00) / 10.00);
    
    }

  2. #2
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    14,859
    Not mentioned which Teensy #.#?

    Problem is likely the Teensy is so fast it saturates the USB line faster than the Serial Monitor can hope to display.

    Replace loop() with this::
    Code:
    void loop()
    {
      static uint32_t lCnt=0;
      uint8_t result;
      ++lCnt;
      if ( !(lCnt%1000) ) {
        //Need data from starting address 0x41 with length 2
        result = node.readHoldingRegisters(0x41, 2);
        Serial.print( micros());
        Serial.print("\t");
        Serial.println(node.getResponseBuffer(0x00) / 10.00);
      }
    
    }
    The above code should give an idea of how much faster taking the difference between the appearance of the micros() value. Run it on the Mega and the Teensy

    That might also slow it down enough on the Teensy to show valid info on SerMon.

    For a better solution perhaps limit the output to a reasonable rate, or only when the value changes.

  3. #3
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    24,775
    Quote Originally Posted by diablodude64 View Post
    it cuts the first digit off from the result and the response rate in the serial monitor changes to about once every second.
    Only once per second is incredibly slow!

    I tried coping your code into Arduino to see if I could do anything to reproduce the problem, but it seems your code in msg #1 isn't a complete program I can actually compile and run.

    Click image for larger version. 

Name:	screenshot.png 
Views:	24 
Size:	67.5 KB 
ID:	25423

  4. #4
    Senior Member
    Join Date
    Apr 2014
    Location
    Cheltenham, UK
    Posts
    365
    Compiled ok for me. You need to download/install modbusmaster.

  5. #5
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    24,775
    Ah, ok. Got the library installed.

    Running it with no hardware connected indeed is slow. Looks like it's waiting 2 seconds, due to this line in ModbusMaster.h.

    Code:
        // Modbus timeout [milliseconds]
        static const uint16_t ku16MBResponseTimeout          = 2000; ///< Modbus timeout [milliseconds]
    I edited this to 100, and indeed it prints 0.00 much faster!

  6. #6
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    24,775
    While I don't have a modbus device here, I did connect my oscilloscope. Here's the waveforms I see on pins 1 and 2.

    Click image for larger version. 

Name:	file1.png 
Views:	14 
Size:	27.6 KB 
ID:	25429

    I tried changing the code to use the automatic DE pin support in Serial1 rather than the callbacks.

    Code:
    #include <ModbusMaster.h>
    
    #define MAX485_DE 2 //Enable transmit pin for MAX485 (both RE/DE tied together)
    
    // instantiate ModbusMaster object
    ModbusMaster node;
    
    void setup()
    {
      pinMode(MAX485_DE, OUTPUT);
      digitalWrite(MAX485_DE, 0);
    
      // Baudrate for serial monitor if you want to see responses
      while (!Serial);
      Serial.begin(38400);
    
      //Baudrate of modbus device is 38400
      while (!Serial1);
      Serial1.begin(38400);
      Serial1.transmitterEnable(MAX485_DE);
    
      // Modbus slave ID is 9 and MAX485 is connected to RX1/TX1
      node.begin(9, Serial1);
    }
    
    void loop()
    {
      uint8_t result;
      //Need data from starting address 0x41 with length 2
      result = node.readHoldingRegisters(0x41, 2);
    
      Serial.println(node.getResponseBuffer(0x00) / 10.00);
    
    }
    Looks like pretty much the same result.

    Click image for larger version. 

Name:	file2.png 
Views:	22 
Size:	27.4 KB 
ID:	25430

  7. #7
    Quote Originally Posted by PaulStoffregen View Post
    While I don't have a modbus device here, I did connect my oscilloscope. Here's the waveforms I see on pins 1 and 2.

    Click image for larger version. 

Name:	file1.png 
Views:	14 
Size:	27.6 KB 
ID:	25429

    I tried changing the code to use the automatic DE pin support in Serial1 rather than the callbacks.

    Code:
    #include <ModbusMaster.h>
    
    #define MAX485_DE 2 //Enable transmit pin for MAX485 (both RE/DE tied together)
    
    // instantiate ModbusMaster object
    ModbusMaster node;
    
    void setup()
    {
      pinMode(MAX485_DE, OUTPUT);
      digitalWrite(MAX485_DE, 0);
    
      // Baudrate for serial monitor if you want to see responses
      while (!Serial);
      Serial.begin(38400);
    
      //Baudrate of modbus device is 38400
      while (!Serial1);
      Serial1.begin(38400);
      Serial1.transmitterEnable(MAX485_DE);
    
      // Modbus slave ID is 9 and MAX485 is connected to RX1/TX1
      node.begin(9, Serial1);
    }
    
    void loop()
    {
      uint8_t result;
      //Need data from starting address 0x41 with length 2
      result = node.readHoldingRegisters(0x41, 2);
    
      Serial.println(node.getResponseBuffer(0x00) / 10.00);
    
    }
    Looks like pretty much the same result.

    Click image for larger version. 

Name:	file2.png 
Views:	22 
Size:	27.4 KB 
ID:	25430

    Thank you for digging into this. I played around with it a little more and plugged into my oscilloscope with the Arduino and then the Teensy and compared the two graphs and they look the same. I then changed from the callbacks for the transmit enable pin to what you have using 'Serial1.transmitterEnable' and now I get the correct numbers in the serial monitor and it's very quick as i'd expect.

    I believe that time-out applies to when the modbus request doesn't get a response? That being the case, what would using the transmitterEnable function change about this?

  8. #8
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    24,775
    Letting the serial driver code control DE gives probably accurate timing.

    If the transmitter turns off too soon, it could cause the outgoing message to be truncated slightly and maybe the other device hears an invalid message (or detects noise or disruption during the stop bit) and doesn't reply? Or if it turns off too late, maybe the transmitter might still be enabled just as the other device starts to reply? If the beginning of the incoming stop bit is cut off, the entire incoming message could be received wrong because the UART paces where it will sample each bit based on timing from the falling edge of the start bit.

    Most well designed half duplex devices use a "turnaround delay", where slave / sensor devices pauses for a brief time before transmitting a reply, and the master / controller waits a brief time before transmitting another request. 1 ms is a typical delay, at least in RS485 devices I've used in the distant past. Devices with little or no turnaround delay communicate slightly faster, but it's risky if the timing changes slightly.

  9. #9
    Okay so I'm back at it and I found something that I don't quite understand. First, it stopped broadcasting new data and I didn't change anything. So I started playing around with the wires to see if something was up there. When I unplug the GND from the MAX485 board, everything works. Which doesn't make sense because there isn't another ground on the board. So by process of elimination I started checking what else would be acting as a ground as the LED on the max485 chip stays lit when the actual ground is disconnected. Turns out the transmitterEnable wire is the culprit which is just plugged into PIN 2 on the Teensy.

    Any idea what would be going on there?

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •