Forum Rule: Always post complete source code & details to reproduce any issue!
Page 2 of 3 FirstFirst 1 2 3 LastLast
Results 26 to 50 of 67

Thread: Serial Problem

  1. #26
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    7,109
    Paul: The GOTCHA here seems like it may be a baud rate mismatch - is there a chance it is triggering the Serial fault detect deadlock for mismatched Start/End on the byte?

    You have looked at this and a possible fix in hand - do you have a link to that I could try?

    <edit>: serial framing errors :: Receive-Lockup-after-first-Write-in-RS485-circuit

  2. #27
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    18,696
    What exactly is meant by "the Serial fault detect deadlock"?

    Currently the only known issue is ~9 bit idle time for recovery from a framing error (where the line is low during the stop bit). That's hardly a "deadlock" where communication can't recover.

  3. #28
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    7,109
    Quote Originally Posted by PaulStoffregen View Post
    What exactly is meant by "the Serial fault detect deadlock"?

    Currently the only known issue is ~9 bit idle time for recovery from a framing error (where the line is low during the stop bit). That's hardly a "deadlock" where communication can't recover.
    Link was previously edited in post above after I found it … indeed … serial framing error was where I was thinking … which it seems does not apply as I recalled there was a case where that or something resulted in Serial stopping.

    In the Normal case of use with the Adafruit GPS it will run well without issue as noted. Current edit from prior post has completed nearly 1500 loop()'s at 1 per second with no Gotcha

  4. #29
    Member
    Join Date
    Oct 2018
    Location
    London
    Posts
    23
    defragster: your test results are in agreement with my findings.

    I regularly use Teensy with Adafruit GPS running at 10 Hz updates, for hour long sessions while recording all data to SD. I never see problems while running. The system is really stable and very reliable. The only problems I ever see are at start up when we have baud rate mismatch. My work-around was to automatically restart Teensy when Serial drops out.

    defragster: having a better understanding of what is happening than I, how would you modify the bare-bones to make it fail straight away? How do you make a framing error?

    Quote Originally Posted by microderm View Post
    So far, tests have revealed two problem types:
    1) Serial1 breaks, and a calling Serial1.begin(9600) does not fix it.
    2) Serial1 claims to receive data. The data is all null, (not real).
    And just to clarify, the second problem mentioned (post #8), I believe was an imaginary problem, just that of viewing data at wrong baud rate, hence zero value. Each time I saw this (since posting), I switched baud and could then see the real data.

  5. #30
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    18,696
    Quote Originally Posted by microderm View Post
    How do you make a framing error?
    The code I posted on msg #28 on that RS485 thread creates serial data on pin2 with a framing error, using IntervalTimer and digitalWrite. The idea is you connect a wire from pin 2 to pin 0, so Serial1 can try to receive the data.

    That issue is on my list to of bugs to investigate and fix. Currently I'm working on other stuff, so probably won't get to it for several days.

    Likewise, for this (still unknown) issue, waiting on the GPS. Got a shipping notice from Adafruit on Sunday. But today was a federal holiday, so no postal service. I'm pretty sure it'll actually go into the mail tomorrow. New York to Oregon usually takes about 3-4 business days for postal mail, so expect to get the GPS by the weekend.

    This other work on my desk at the moment is pretty important, so can't promise any particular time frame. I can tell you this baud rate issue (for lack of a better phase so far) is on my list to investigate, but so far I'm not considering it a bug. That framing error recovery is a bug. It's also on hold for now. When I do work on it, one of the first things I'm going to do is look at how other Arduino compatible boards handle recovery from that framing error....

  6. #31
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    7,109
    re Paul's post #30 - the link to post #28 is what I linked to in this thread post #26.

    By Deadlock - I meant only to infer that the Serial1 hardware doesn't recover - though the code keeps running as indicated. Once the FE triggers on Serial1 it doesn't seem to resume?

    Using that posted ( other thread #28 ) code and added setup :: the Pin 0<>2 setup indeed I find this is the case - not having a scope:
    Code:
      if (UART0_S1 & UART_S1_FE) Serial.println("FRAMING ERROR !! b");
    NOTE:: With a Button pulled up on pin 2 it requires hardware changes to swap these sketches on the same T_3.6 board.
    >> @microderm: if you can add code below to the GOTCHA location [ and see it trigger ] and move the pin #2 button elsewhere and repost that code it would allow Paul to easily test both without changing the hardware.

    Using that test of "UART_S1_FE" I put that in the code above on this thread - when reverted to the GOTCHA case - and indeed it reports a framing error:
    Code:
    FRAMING ERROR !! d
    ******************** Gotcha! ********************
    Here is that code in place in the posted code:
    Code:
    void serialCheck() {
      Serial.println("");
      if (UART0_S1 & UART_S1_FE) {
        Serial.println("FRAMING ERROR !! d");
        delay(2000);
      }
      if (!serial1_count && !Serial1.available()) {
        Serial.println("******************** Gotcha! ********************");

  7. #32
    Member
    Join Date
    Oct 2018
    Location
    London
    Posts
    23
    I had a little play with the frame error code. I found that once the frame error had occurred, a simple call to Serial1.begin(9600) did not fix the problem. As long as you keep pumping in data, the error persists, even if you call Serial1.end() then sometime later Serial1.begin(9600).

    This looks similar to the problem I have been experiencing. But, I think Paul believes that it won't be the same problem since a small pause in data stream releases the frame error.

    The GPS unit pumps out data continuously until all info has been sent then waits for the next data cycle. So there will be pauses in communication:

    Assuming 4 packets sent at 70 chars each, we have 280 chars of data.

    Pause time calculation:
    1) 9600 baud (updates every 1000 ms) => 960 chars / s. Time required = 280 / 960 = 0.2916 s = 291.6 ms.
    Pause: 1000 - 291.6 = 708.4 ms.
    2) 115200 baud (updates every 100 ms) => 11520 chars / s. Time required = 280 / 11520 = 0.0243 secs = 24.3 ms.
    Pause: 100 - 24.3 = 75.7 ms.

    Clearly the pause is sufficient to release any frame error.

    In addition I had a little play with this idea by modifying the frame error code to keep writing data in a loop after the frame error. I then connected the GPS output to pin 0 then removed the data stream from pin 2. During the period where both were plugged in together, the frame error persisted. When I pulled out the connection to pin 2, the frame error would release either immediately, or shortly afterwards, depending on where it was in the GPS data stream cycle.

    It may have been more elegant to have modified the circuit to use a couple of AND gates, a NOT gate and an OR gate, so that data stream input could be hot swapped instantly by a single output pin, but I thought that the quick manual method would suffice.

    My conclusions are that my problem is a different problem to frame error.

    I'll have a little play with (UART0_S1 & UART_S1_FE) in the bare-bones test tomorrow.

    Paul: There's no need to hurry to look into this. It's a rare problem and I have simple work-arounds.

  8. #33
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    7,109
    If as suggested the test shown reads UART status - it is indicating a frame error same in both sketches. Didn't read the book - just the PJRC codebase where that was #defined.

    So in the GPS sketch the EN pin could be switched for a short time to stop the GPS output stream and based on the findings above the Frame Error will clear?

  9. #34
    Member
    Join Date
    Oct 2018
    Location
    London
    Posts
    23
    defragster: I had a play with the (UART0_S1 & UART_S1_FE) code as suggested. First, I put it in the Gotcha code and found as you did that it was flagged there. I then used it as a diagnostic tool:
    Code:
    void testUART(int id) {
      if (serial1 && (UART0_S1 & UART_S1_FE)) {
        Serial.println("******************** (" + String(id) + ") UART_S1_FE Gotcha! {" + String(UART0_S1) + "," + String(UART_S1_FE) + "} ********************");
      }
    }
    I inserted this function in the code at key stages and within the timing loops so I could see when the status changed in greater detail. The id parameter allowed me call the function using different ids so that I would know at which stage the report referred to. Printout of one run shown below, edited with ... to shorten long lists of same data:
    Code:
    *** Setup init *** 
    *** Setup complete *** 
    
    *** Loop *** 
    ************************************************************
    ******************** Restart Sequence 1 ********************
    ************************************************************
    <3>
    *** Setting 9600 baud ***
    [time] (baud) packet-data
    <4>
    [2011] (9600) $PGACK,103*40
    [2023] (9600) $PGACK,105*46
    [2040] (9600) $PMTK011,MTKGPS*08
    [2061] (9600) $PMTK010,001*2E
    [2077] (9600) $PMTK010,002*2D
    [2913] (9600) $GPGGA,235942.800,,,,,0,00,,,M,,M,,*7B
    [2955] (9600) $GPGSA,A,1,,,,,,,,,,,,,,,*1E
    [2985] (9600) $GPRMC,235942.800,V,,,,,0.00,0.00,050180,,,N*42
    [3035] (9600) $GPVTG,0.00,T,,M,0.00,N,0.00,K,N*32
    *** Setting 115200 baud ***
    [time] (baud) packet-data
    *** PMTK_SET_DATA_100MS ***
    [3929] (115200) $GPGGA,235943.800,,,,,0,00,,,M,,M,,*7A
    [3932] (115200) $GPGSA,A,1,,,,,,,,,,,,,,,*1E
    [3935] (115200) $GPRMC,235943.800,V,,,,,0.00,0.00,050180,,,N*43
    [3940] (115200) $GPVTG,0.00,T,,M,0.00,N,0.00,K,N*32
    
    serialCheck(avail: 0, count: 396) = ok
    
    **********************************************************
    ******************** Toggle Baud Rate ********************
    **********************************************************
    *** Setting 9600 baud ***
    [time] (baud) packet-data
    
    *** Loop *** 
    ************************************************************
    ******************** Restart Sequence 2 ********************
    ************************************************************
    <3>
    *** Setting 9600 baud ***
    [time] (baud) packet-data
    <4>
    ******************** (220) UART_S1_FE Gotcha! {198,2} ********************
    ******************** (221) UART_S1_FE Gotcha! {192,2} ********************
    ******************** (401) UART_S1_FE Gotcha! {198,2} ********************
    ******************** (402) UART_S1_FE Gotcha! {198,2} ********************
    ******************** (403) UART_S1_FE Gotcha! {198,2} ********************
    *** Setting 115200 baud ***
    [time] (baud) packet-data
    *** PMTK_SET_DATA_100MS ***
    [7453] (115200) $PMTK001,220,3*30
    
    serialCheck(avail: 0, count: 24) = ok
    
    **********************************************************
    ******************** Toggle Baud Rate ********************
    **********************************************************
    *** Setting 9600 baud ***
    [time] (baud) packet-data
    ******************** (130) UART_S1_FE Gotcha! {198,2} ********************
    ******************** (131) UART_S1_FE Gotcha! {198,2} ********************
    ******************** (132) UART_S1_FE Gotcha! {198,2} ********************
    
    *** Loop *** 
    ************************************************************
    ******************** Restart Sequence 3 ********************
    ************************************************************
    <3>
    *** Setting 9600 baud ***
    [time] (baud) packet-data
    <4>
    ******************** (4) UART_S1_FE Gotcha! {134,2} ********************
    ******************** (100) UART_S1_FE Gotcha! {134,2} ********************
    ******************** (101) UART_S1_FE Gotcha! {198,2} ********************
    ******************** (102) UART_S1_FE Gotcha! {198,2} ********************
    ...
    ******************** (597) UART_S1_FE Gotcha! {198,2} ********************
    ******************** (598) UART_S1_FE Gotcha! {198,2} ********************
    ******************** (599) UART_S1_FE Gotcha! {198,2} ********************
    ******************** (5) UART_S1_FE Gotcha! {198,2} ********************
    ******************** (6) UART_S1_FE Gotcha! {198,2} ********************
    ******************** (7) UART_S1_FE Gotcha! {198,2} ********************
    *** Setting 115200 baud ***
    [time] (baud) packet-data
    ******************** (8) UART_S1_FE Gotcha! {198,2} ********************
    *** PMTK_SET_DATA_100MS ***
    ******************** (100) UART_S1_FE Gotcha! {6,2} ********************
    ******************** (101) UART_S1_FE Gotcha! {198,2} ********************
    ******************** (102) UART_S1_FE Gotcha! {198,2} ********************
    ...
    ******************** (197) UART_S1_FE Gotcha! {198,2} ********************
    ******************** (198) UART_S1_FE Gotcha! {198,2} ********************
    ******************** (199) UART_S1_FE Gotcha! {198,2} ********************
    
    ******************** (0) UART_S1_FE Gotcha! {198,2} ********************
    ******************** Gotcha! ********************
    
    ******************** (9) UART_S1_FE Gotcha! {198,2} ********************
    ******************** (100) UART_S1_FE Gotcha! {198,2} ********************
    ******************** (101) UART_S1_FE Gotcha! {198,2} ********************
    ******************** (102) UART_S1_FE Gotcha! {198,2} ********************
    ...
    ******************** (147) UART_S1_FE Gotcha! {198,2} ********************
    ******************** (148) UART_S1_FE Gotcha! {198,2} ********************
    ******************** (149) UART_S1_FE Gotcha! {198,2} ********************
    **********************************************************
    ******************** Toggle Baud Rate ********************
    **********************************************************
    *** Setting 9600 baud ***
    [time] (baud) packet-data
    ******************** (100) UART_S1_FE Gotcha! {198,2} ********************
    ******************** (101) UART_S1_FE Gotcha! {198,2} ********************
    ******************** (102) UART_S1_FE Gotcha! {198,2} ********************
    ...
    ******************** (147) UART_S1_FE Gotcha! {198,2} ********************
    ******************** (148) UART_S1_FE Gotcha! {198,2} ********************
    ******************** (149) UART_S1_FE Gotcha! {198,2} ********************
    
    *** Loop *** 
    ************************************************************
    ******************** Restart Sequence 4 ********************
    ************************************************************
    <3>
    *** Setting 9600 baud ***
    [time] (baud) packet-data
    <4>
    ******************** (4) UART_S1_FE Gotcha! {134,2} ********************
    ******************** (100) UART_S1_FE Gotcha! {134,2} ********************
    ******************** (101) UART_S1_FE Gotcha! {198,2} ********************
    ******************** (102) UART_S1_FE Gotcha! {198,2} ********************
    ...
    I tried switching off the the GPS unit when flagged at the Gotcha stage. It didn't work in my tests, but I believe it might work sometimes, depending on which error code were flagged. I don't know what the numbers mean, but it seems that some are more severe than others. I think UART0_S1=134 is the kiss of death!

    My current thoughts are that there is no real reliable way to talk to a device with unknown baud rate, without:
    a) possibly having to restart Teensy.
    b) be prepared to kill one serial port along the way (the one that did not match the incoming data rate).

    Failure seems to be a little temperamental, as the details of the timing mismatch appear to be crucial.

    One idea I had was to set a flag in EPROM to suggest which baud rate to try, so that a restart will result in best match each time thereafter.

  10. #35
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    7,109
    Good work. If you cleaned that up and posted a fresh working set of code it might help Paul test any fix he can come up with for his overt framing error that might also catch the case of mismatched baud issues.

    The function with the ID param is nice, I just pasted the code a few places and that is what that trailing letter to identify the calling line 'd' is :: "FRAMING ERROR !! d". You could also pass __LINE__ as a parameter and then print the 'int __lineno'.

    Those flag bits are defined here where UART0 is of course Serial1. If you broke those out it might indicate show what #134>>10000110 means in English - is it the NOISE flag that pops up for 'kiss of death'?:
    Code:
    T:\arduino_1.8.6\hardware\teensy\avr\cores\teensy3\kinetis.h:
     4792  #define UART0_S1		(KINETISK_UART0.S1)		// UART Status Register 1
     4793: #define UART_S1_TDRE		0x80			//  Transmit Data Register Empty Flag
     4794: #define UART_S1_TC		0x40			//  Transmit Complete Flag
     4795: #define UART_S1_RDRF		0x20			//  Receive Data Register Full Flag
     4796: #define UART_S1_IDLE		0x10			//  Idle Line Flag
     4797: #define UART_S1_OR		0x08			//  Receiver Overrun Flag
     4798: #define UART_S1_NF		0x04			//  Noise Flag
     4799: #define UART_S1_FE		0x02			//  Framing Error Flag
     4800: #define UART_S1_PF		0x01			//  Parity Error Flag
    Mismatched baud would seem to be temperamental by nature. The Rx hardware is parsing the transitions from the GPS at the wrong rate and trying to sync and make sense of it and it never will - and a given pattern will trigger panic. Keeping track of the baud in use for reliable operation would be important, until the battery fails or whatever might cause a factory reset.

    Perhaps in setup() open at expected baud rate and read some bytes looking for an expected string. If not found then go to alternate baud rate and repeat that test. Then respond accordingly with baud change and perhaps Teensy reset to start fresh.

  11. #36
    Member
    Join Date
    Oct 2018
    Location
    London
    Posts
    23
    Quote Originally Posted by defragster View Post
    If you cleaned that up and posted a fresh working set of code it might help Paul test any fix
    I'll try to have something a lot simpler for Paul to look at in a coupe of days. I made the system complex so that I could experiment.

    Using __LINE__ is smart. I'd forgotten that macro. Thanks for the breakdown codes, it really helps to make sense of the numbers.

    When I experiment with this again, I'll test the idea that certain flag values indicate irreversible breakdown of serial comms. I'm not yet sure that's the case. I saw a pattern like that with a few runs of the code, but I didn't then immediately switch to the correct baud rate to test whether recovery was still possible.

    At the moment I'm implementing that start procedure. I now have the battery in place so the module starts faster and never fails. I'll need to implement the EPROM idea too, to encourage subsequent starts to use the perceived starting rate.

    Something else that might be nice is to know is whether Teensy has just cold booted, re-booted itself or just been re-programmed. Is that kind of info laying around in registers somewhere?

  12. #37
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    7,109
    yes, found this on forum somewhere. This is what I was thinking of when I wrote "... show what #134>>10000110 means in English"

    Code:
    int resetReasonHw;
      resetReasonHw = RCM_SRS0;
      resetReasonHw |= (RCM_SRS1 << 8);
      if ( Serial )
      resetReason( resetReasonHw );
    calls out to this:
    Code:
    void resetReason( int resetReasonHw ) {
      uint16_t mask = 1;
      //  Serial.print(strReason);
      Serial.print(">>> Reason for 'reset': ");
      Serial.print(resetReasonHw, HEX);
      do {
        switch (mask & resetReasonHw) {
          //RCM_SRS0
          case 0x0001: Serial.print(F(" wakeup")); break;
          case 0x0002: Serial.print(F(" LowVoltage"));  break;
          case 0x0004: Serial.print(F(" LossOfClock")); break;
          case 0x0008: Serial.print(F(" LossOfLock")); break;
          //case 0x0010 reserved
          case 0x0020: Serial.print(F(" wdog")); break;
          case 0x0040: Serial.print(F(" ExtResetPin")); break;
          case 0x0080: Serial.print(F(" PwrOn")); break;
    
          //RCM_SRS1
          case 0x0100: Serial.print(F(" JTAG")); break;
          case 0x0200: Serial.print(F(" CoreLockup")); break;
          case 0x0400: Serial.print(F(" SoftWare")); break;
          case 0x0800: Serial.print(F(" MDM_AP")); break;
    
          case 0x1000: Serial.print(F(" EZPT")); break;
          case 0x2000: Serial.print(F(" SACKERR")); break;
            //default:  break;
        }
      } while (mask <<= 1);
      Serial.println(" :: done Reason");
    }

  13. #38
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    3,704
    Maybe I will have to play along soon. I did just receive one of those shiny boards in the mail yesterday...

  14. #39
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    7,109
    @KurtE - Posts 30-31 give a simple start point with the explicit case Paul made - with the test.

    A simpler baud swap from microderm might be easier than the prior

  15. #40
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    3,704
    Quote Originally Posted by defragster View Post
    @KurtE - Posts 30-31 give a simple start point with the explicit case Paul made - with the test.

    A simpler baud swap from microderm might be easier than the prior
    I guess the real question is, what is the minimal hardware you need to setup for this? Do you need the buttons and the like? And what is the latest software you are running?
    The files from the zip file on page one updated with ???

  16. #41
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    3,704
    If it turns into a Framing error, I wonder what would happen if we just added test/recovery to serial objects.

    Like what happens if you change Serial1.c in avr\cores\teensy3 like:
    Code:
    void uart0_status_isr(void)
    {
    	uint32_t head, tail, n;
    	uint8_t c;
    #ifdef HAS_KINETISK_UART0_FIFO
    	uint32_t newhead;
    	uint8_t avail;
    	if (UART0_S1 & UART_S1_FE) {
    		// Framing error
    		c = UART0_D;	// read data to clear it out
    	}
    
    	if (UART0_S1 & (UART_S1_RDRF | UART_S1_IDLE)) {
    		__disable_irq();
    		avail = UART0_RCFIFO;
    		if (avail == 0) {
    ...
    New stuff in RED...

    So it sees that the Frame error is in place and then reads the data word, which the manual says should clear out the framing error.

    If this works OK, would need to replicate in the other Serial[1-6].c files...

    Note it is interesting that I have not seen this (maybe I have and did not recognize it). But for example with some of my robot code that uses XBees, it first tries to communicate with the XBee at the baud rate that I expect and if that fails, it then tries at the default baud rate for XBee... And if that works it re configures the XBEE to the desired baud rate.

  17. #42
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    7,109
    Quote Originally Posted by KurtE View Post
    I guess the real question is, what is the minimal hardware you need to setup for this? Do you need the buttons and the like? And what is the latest software you are running?
    The files from the zip file on page one updated with ???
    I added buttons - but they can perhaps be skipped as they just added complication. An edit and recompile can make it work 'programmatically' as I saw it without touching a button. The LED was nice to see in case a trapped error scrolled off, but the pin 13 LED would work for that.

    I used the prior posted code and then added the _FE test as noted in the post - both in Paul's other thread code and then in this code.

    … Next Post::
    Paul's code just does perpetual repro on the _FE, but in this GPS case it might go back to running with that test. You could see what that 'auto clear' code does to the function of that sketch? Maybe Paul's code could manage a string of good characters between forced _FE's? Maybe forcing it on a button press would give a user and scope trigger?

    I didn't look into the mechanics/process of the baud change in the GPS code to understand what step was causing the _FE to occur. When in 'testing==true' mode it makes a few calls to the button functions in some fashion and I didn't follow long enough to understand what the GPS baud was and what it was doing to change the Teensy and or GPS rate leading to the _FE … I just added the detecting in sync with the GOTCHA code to see it was really finding a failed state.

    If @microderm could make an example that perhaps runs/works, and then does the baud change trigger [rather than auto cycling while in test mode] on a button press it would make the repro case clearer to cause and correct.


    As far as xBee - it seems to work for 'some time' - It may be the exact data stream from the GPS is causing the GOTCHA where the timing is exactly wrong.

  18. #43
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    3,704
    I hacked on the original code:
    Code:
    /*
     * Controller : OpenCM9.04 with 485 EXP board
     * Dynamixel : MX-28/64/106(with Protocol 2.0), X-series(except XL-320)
     * Power source : 12V SMPS to 485 EXP board(or 24V for Dynamixel Pro series)
     * 
     * Dynamixels are connected to Dynamixel BUS on 485 EXP board
     * http://emanual.robotis.com/docs/en/parts/controller/opencm485exp/#layout
    */
    
    #include <DynamixelSDK.h>
    
    // Control table address could be differ by Dynamixel Series
    #define ADDRESS_TORQUE_ENABLE           64
    #define ADDRESS_LED                     65
    #define ADDRESS_GOAL_POSITION           116
    #define ADDRESS_PRESENT_POSITION        132
    
    // Data Byte Length
    #define LENGTH_LED                      1
    #define LENGTH_GOAL_POSITION            4
    #define LENGTH_PRESENT_POSITION         4
    
    // Protocol version
    #define PROTOCOL_VERSION                2.0                 // See which protocol version is used in the Dynamixel
    
    // Default setting
    #define DXL1_ID                         1                   // Dynamixel#1 ID: 1
    #define DXL2_ID                         2                   // Dynamixel#2 ID: 2
    #define BAUDRATE                        1000000
    #define DEVICENAME                      "1"                 // Check which port is being used on your controller
                                                                // DEVICENAME "1" -> Serial1
                                                                // DEVICENAME "2" -> Serial2
                                                                // DEVICENAME "3" -> Serial3(OpenCM 485 EXP)
    
    #define TORQUE_ENABLE                   1                   // Value for enabling the torque
    #define TORQUE_DISABLE                  0                   // Value for disabling the torque
    #define DXL_MINIMUM_POSITION_VALUE      100                 // Dynamixel will rotate between this value
    #define DXL_MAXIMUM_POSITION_VALUE      4000                // and this value (note that the Dynamixel would not move when the position value is out of movable range. Check e-manual about the range of the Dynamixel you use.)
    #define DXL_MOVING_STATUS_THRESHOLD     20                  // Dynamixel moving status threshold
    
    #define ESC_ASCII_VALUE                 0x1b
    
    
    
    void setup() {
      // put your setup code here, to run once:
      Serial.begin(115200);
      while(!Serial);
    
    
      Serial.println("Start..");
    
       // Initialize PortHandler instance
      // Set the port path
      // Get methods and members of PortHandlerLinux or PortHandlerWindows
      dynamixel::PortHandler *portHandler = dynamixel::PortHandler::getPortHandler(DEVICENAME);
    
      // Initialize PacketHandler instance
      // Set the protocol version
      // Get methods and members of Protocol1PacketHandler or Protocol2PacketHandler
      dynamixel::PacketHandler *packetHandler = dynamixel::PacketHandler::getPacketHandler(PROTOCOL_VERSION);
    
      // Initialize GroupBulkWrite instance
      dynamixel::GroupBulkWrite groupBulkWrite(portHandler, packetHandler);
    
      // Initialize GroupBulkRead instance
      dynamixel::GroupBulkRead groupBulkRead(portHandler, packetHandler);
    
      int index = 0;
      int dxl_comm_result = COMM_TX_FAIL;             // Communication result
      bool dxl_addparam_result = false;                // addParam result
      bool dxl_getdata_result = false;                 // GetParam result
      int dxl_goal_position[2] = {DXL_MINIMUM_POSITION_VALUE, DXL_MAXIMUM_POSITION_VALUE};         // Goal position
    
      uint8_t dxl_error = 0;                          // Dynamixel error
      uint8_t dxl_led_value[2] = {0x00, 0x01};        // Dynamixel LED value for write
      uint8_t param_goal_position[4];
      int32_t dxl1_present_position = 0;              // Present position
      uint8_t dxl2_led_value_read;                    // Dynamixel LED value for read
    
      // Open port
      if (portHandler->openPort())
      {
        Serial.print("Succeeded to open the port!\n");
      }
      else
      {
        Serial.print("Failed to open the port!\n");
        Serial.print("Press any key to terminate...\n");
        return;
      }
    
      // Set port baudrate
      if (portHandler->setBaudRate(BAUDRATE))
      {
        Serial.print("Succeeded to change the baudrate!\n");
      }
      else
      {
        Serial.print("Failed to change the baudrate!\n");
        Serial.print("Press any key to terminate...\n");
        return;
      }
    
      // Enable Dynamixel#1 Torque
      dxl_comm_result = packetHandler->write1ByteTxRx(portHandler, DXL1_ID, ADDRESS_TORQUE_ENABLE, TORQUE_ENABLE, &dxl_error);
      if (dxl_comm_result != COMM_SUCCESS)
      {
        packetHandler->getTxRxResult(dxl_comm_result);
      }
      else if (dxl_error != 0)
      {
        packetHandler->getRxPacketError(dxl_error);
      }
    
      // Enable Dynamixel#2 Torque
      dxl_comm_result = packetHandler->write1ByteTxRx(portHandler, DXL2_ID, ADDRESS_TORQUE_ENABLE, TORQUE_ENABLE, &dxl_error);
      if (dxl_comm_result != COMM_SUCCESS)
      {
        packetHandler->getTxRxResult(dxl_comm_result);
      }
      else if (dxl_error != 0)
      {
        packetHandler->getRxPacketError(dxl_error);
      }
    
      // Add parameter storage for Dynamixel#1 present position
      dxl_addparam_result = groupBulkRead.addParam(DXL1_ID, ADDRESS_PRESENT_POSITION, LENGTH_PRESENT_POSITION);
    
      // Add parameter storage for Dynamixel#2 LED value
      dxl_addparam_result = groupBulkRead.addParam(DXL2_ID, ADDRESS_LED, LENGTH_LED);
    
      while(1)
      {
        Serial.print("Press any key to continue! (or press q to quit!)\n");
    
    
        while(Serial.available()==0);
    
        int ch;
    
        ch = Serial.read();
        if( ch == 'q' )
          break;
    
        // Allocate goal position value into byte array
        param_goal_position[0] = DXL_LOBYTE(DXL_LOWORD(dxl_goal_position[index]));
        param_goal_position[1] = DXL_HIBYTE(DXL_LOWORD(dxl_goal_position[index]));
        param_goal_position[2] = DXL_LOBYTE(DXL_HIWORD(dxl_goal_position[index]));
        param_goal_position[3] = DXL_HIBYTE(DXL_HIWORD(dxl_goal_position[index]));
    
        // Add parameter storage for Dynamixel#1 goal position
        dxl_addparam_result = groupBulkWrite.addParam(DXL1_ID, ADDRESS_GOAL_POSITION, LENGTH_GOAL_POSITION, param_goal_position);
    
        // Add parameter storage for Dynamixel#2 LED value
        dxl_addparam_result = groupBulkWrite.addParam(DXL2_ID, ADDRESS_LED, LENGTH_LED, &dxl_led_value[index]);
    
        // Bulkwrite goal position and LED value
        dxl_comm_result = groupBulkWrite.txPacket();
        if (dxl_comm_result != COMM_SUCCESS) packetHandler->getTxRxResult(dxl_comm_result);
    
        // Clear bulkwrite parameter storage
        groupBulkWrite.clearParam();
    
        do
        {
          // Bulkread present position and LED status
          dxl_comm_result = groupBulkRead.txRxPacket();
          if (dxl_comm_result != COMM_SUCCESS) packetHandler->getTxRxResult(dxl_comm_result);
    
          // Check if groupbulkread data of Dynamixel#1 is available
          dxl_getdata_result = groupBulkRead.isAvailable(DXL1_ID, ADDRESS_PRESENT_POSITION, LENGTH_PRESENT_POSITION);
    
          // Check if groupbulkread data of Dynamixel#2 is available
          dxl_getdata_result = groupBulkRead.isAvailable(DXL2_ID, ADDRESS_LED, LENGTH_LED);
    
          // Get present position value
          dxl1_present_position = groupBulkRead.getData(DXL1_ID, ADDRESS_PRESENT_POSITION, LENGTH_PRESENT_POSITION);
    
          // Get LED value
          dxl2_led_value_read = groupBulkRead.getData(DXL2_ID, ADDRESS_LED, LENGTH_LED);
    
          Serial.print("[ID:");      Serial.print(DXL1_ID);
          Serial.print(" PresPos:");  Serial.print(dxl1_present_position);
          Serial.print(" [ID:");      Serial.print(DXL2_ID);
          Serial.print(" LED Value:");  Serial.print(dxl2_led_value_read);
          Serial.println(" ");
    //      printf("[ID:%03d] Present Position : %d \t [ID:%03d] LED Value: %d\n", DXL1_ID, dxl1_present_position, DXL2_ID, dxl2_led_value_read);
    
        }while(abs(dxl_goal_position[index] - dxl1_present_position) > DXL_MOVING_STATUS_THRESHOLD);
    
        // Change goal position
        if (index == 0)
        {
          index = 1;
        }
        else
        {
          index = 0;
        }
      }
    
      // Disable Dynamixel#1 Torque
      dxl_comm_result = packetHandler->write1ByteTxRx(portHandler, DXL1_ID, ADDRESS_TORQUE_ENABLE, TORQUE_DISABLE, &dxl_error);
      if (dxl_comm_result != COMM_SUCCESS)
      {
        packetHandler->getTxRxResult(dxl_comm_result);
      }
      else if (dxl_error != 0)
      {
        packetHandler->getRxPacketError(dxl_error);
      }
    
      // Disable Dynamixel#2 Torque
      dxl_comm_result = packetHandler->write1ByteTxRx(portHandler, DXL2_ID, ADDRESS_TORQUE_ENABLE, TORQUE_DISABLE, &dxl_error);
      if (dxl_comm_result != COMM_SUCCESS)
      {
        packetHandler->getTxRxResult(dxl_comm_result);
      }
      else if (dxl_error != 0)
      {
        packetHandler->getRxPacketError(dxl_error);
      }
    
      // Close port
      portHandler->closePort();
    
    
    }
    
    void loop() {
      // put your main code here, to run repeatedly:
    
    }
    As I added three buttons. But did not want to add extra stuff for the Button library, so hooked them up and used the bounce library.

    Will see if there is something that causes it to reproduce...

  19. #44
    Member
    Join Date
    Oct 2018
    Location
    London
    Posts
    23
    Thanks for looking at this guys. I can't play along right now, the board's in use. Hopefully later tomorrow.

  20. #45
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    18,696
    The GPS arrived from Adafruit. I've got it wired up on my desk right now.

    Click image for larger version. 

Name:	DSC_0244_web.jpg 
Views:	7 
Size:	177.0 KB 
ID:	14961

    Quote Originally Posted by microderm View Post
    I'll try to have something a lot simpler for Paul to look at in a coupe of days. I made the system complex so that I could experiment.
    Which code should I run, and what should I do to observe the error?

  21. #46
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    18,696
    I added the enable wire and I'm running the code from msg #23.

    Click image for larger version. 

Name:	DSC_0246_web.jpg 
Views:	6 
Size:	169.9 KB 
ID:	14966

    It seems to be reproducing the problem, but I'm out of time for this today. Will look at it in detail early tomorrow.

  22. #47
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    7,109
    It seems that is the code I ran and saw the issue.

    For fun putting this bold code posted above in the noted function shows it detecting the _FE - as it did on your other thread code:
    Code:
    void serialCheck() {
      Serial.println("");
      if (UART0_S1 & UART_S1_FE) {
        Serial.println("FRAMING ERROR !! d");
        delay(2000);
      }
      if (!serial1_count && !Serial1.available()) {
        Serial.println("******************** Gotcha! ********************");
    That would allow a discrete test anywhere in the code to see it without the GOTCHA testing.

  23. #48
    Member
    Join Date
    Oct 2018
    Location
    London
    Posts
    23
    I tried to simplify the code producing the problem, but it is hard, as the fault is a little temperamental, so code from #23 is good to try.

    I experimented with using the code below as a test of current status:
    Code:
    void testUART(int id) {
      if (serial1 && (UART0_S1 & UART_S1_FE)) {
        Serial.println("******************** (" + String(id) + ") UART_S1_FE Gotcha! {" + String(UART0_S1) + "," + String(UART_S1_FE) + "} ********************");
      }
    }
    For a while, I thought that certain values of UART0_S1 were significant (134 & 6) in leading to Serial failure, but further testing revealed that the first results (suggesting the notion) were purely coincidental. Those values just indicate noise, but not imminent failure.

    I just set the board up again, minus the buttons (as I'm using them elsewhere) and button code, and replaced the hardwired button event calls with the corresponding functions. It works just the same. The buttons are great if you want to try stuff once the failure has occurred.

    KurtE looked like he had a some ideas, but I haven't looked into his code, as I'm not that familiar with the inner workings of the system (so not quite sure where to start).

    Paul: let me know if you want me to try anything this end.

  24. #49
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    7,109
    One way to clean up the output and process would be to leave "testing=true" to cause the problem.

    Though it then keeps cycling. So the code above if edited to stop testing on the _FE detection as follows would at stop baud and other changes:

    Code:
    void serialCheck() {
      Serial.println("");
      if (UART0_S1 & UART_S1_FE) {
        Serial.println("FRAMING ERROR !! d");
        testing = false;
        delay(2000);
      }
      if (!serial1_count && !Serial1.available()) {
        Serial.println("******************** Gotcha! ********************");
    Then as needed other diagnostics and actions could be taken in that state.

  25. #50
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    7,109
    I turned on my setup and starting from the downloaded code I modified the setup to have a starting Serial1( baud ) and modified the loop() code so it detects the _FE and stops testing and stops any changes after that.

    The loop() code below shows the current baud and that is printed each LOOP pass WHILE the _FE exists. The _FE does clear - and return. It seems my GPS is 115200 and it fails when sitting at 9200.

    It is not always failing as fast now - though last time happened after "Restart Sequence 3" - this time again running up to Sequence #50 and counting - just failed at #85, next restart came at #3 again. I suppose this may have to do with the transmitted bit values triggering the _FE?

    The changes below - other than putting setBaud(115200); at the end of setup() should not change anything until a _FE occurs as it was running before.

    At time _FE is detected the LED on Teensy and the added LMP are turned on, if the _FE clears (based on GOTCHA) the LMP turns off, until it recurs - but Pin13 LED stays on.

    setup() code needs to init the baud or the _FE test faults the processor because Serial1 is 'offline':
    Code:
    void setup() {
      // …
      setBaud(115200);
    }
    loop() code as I edited it:
    Code:
    void loop() {
      Serial.println("\n*** Loop *** ");
      if (testing) {
        if (UART0_S1 & UART_S1_FE) {
          Serial.print("FRAMING ERROR !! AT>>");
          Serial.println(__LINE__);
          testing = false;
          serialCheck();
          digitalWrite(LED, HIGH);
          digitalWrite(LMP, LOW); // ON //
          delay(1000);
          return;
        }
        buttonEventHandler(BTN_1, 0); // Attempt to kill Serial - usually doesn't succeed - the force is strong in that one!
        delayMillis(250); // Allow to adjust to higher baud //
        serial1_9600_baud = false; // Toggle to 9600 baud //
        buttonEventHandler(BTN_2, 0); // Restore Serial1 to 9600 baud - will fail to read incoming 115200 baud data //
        delayMillis(250); // Allow to settle in //
      } else if (UART0_S1 & UART_S1_FE) {
        Serial.println("*** CURRENT " + String(curr_baud) + " baud ***");
        serialCheck();
        digitalWrite(LMP, LOW); // ON //
        delayMillis(1000);
      }
      else {
        digitalWrite(LMP, HIGH);
        delayMillis(1000);
      }
    }

Posting Permissions

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