Announcement

Collapse
No announcement yet.

Recover from Serial 4D Library reports error

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • #16
    Your instructions are not very clear. I spent a while trying to change the Picaso baud rate and looking thru documentation.
    The 4D workshop uses a pre-proceesor directive to set the speed
    //%%Display%%.DisplaySerial.Begin_Speed ; // *Replaced* at compile time with command to start the serial port at the correct speed
    After looking at the generated .ino file it converts to this
    DisplaySerial.begin(200000) ;
    I commented out the directive and I tried 56000, 56250, BAUD_56000 and it did not work. If I set it to 200000 it works.

    Also the instruction appears incorrect
    " In 4D Workshop Click on File-->Click on Options-->Click on Serial-->Choose the Serial Environment Baud Rate to 57600."
    This is set to 9600 and controls the communication to the PC I believe.

    I don't know what the SPE_Load does but I did that as well.

    Comment


    • #17
      you will need to change the baud in workshop ide not just the sketch, and then loading SPE back onto your 4duino. there is a header on the back of the 4duino 2x5 header, one side is to reprogram the picaso SPE from workshop to update its baud rate to match the arduino code, the other side is to update the esp8266 module, you will need the usb-pa5 adaptor for that header

      Comment


      • #18
        I did try that but it's not clear how you do that exactly. I tried setting the File->Options->Serial->Initial Baud Rate and changing the code itself then using the SPE Load with the cable connected to the Picaso. It uploaded something but did not seem to change the baud rate.

        Comment


        • #19
          I found some documentation in the Picaso Serial command set and the Serial Picaso Getting Started – the SPE Application guide. Tried again using the above procedure and the SPE load seemed to work but the only speed I could use from the 4duino is 200000.
          It appears that the default setting is 9600 baud and the arduino program sets it to 200000. So does it auto detect or is it set some other way?
          Last edited by dskogman; 21st March 2017, 12:26 PM.

          Comment


          • #20
            Originally posted by Noel View Post
            Dear dskogman,

            I tried running your sketch and it ran for many hours with no error messages although only the 4duino since I do not have the shields. However, can you lower the baud rate of the Picaso display and see if the error still persist?. In 4D Workshop Click on File-->Click on Options-->Click on Serial-->Choose the Serial Environment Baud Rate to 57600. In 4D Workshop click on File-->New-->Choose Arduino-->4duino-->Extended Graphics-->Tools-->SPE Load. Please choose the Serial port of the 4Duino connected through the uUSB-PA5 of the Picaso Programming Header. In your code also change the the code DisplaySerial.begin(200000); to DisplaySerial.begin(57600) ; Please make sure that the 5V power supply of the 4Duino is regulated and capable of delivering more than 320 milli amperes. If not, the output voltage may drop when it enters the current limit and will cause the 4Duino to behave erratically. If the shields draw power from the 4duino
            headers, you will need more the 320 milli ampere. If you are using the USB port to power the 4duino, you may need a self powered hub since most USB ports can only deliver 500 milli amperes.
            Best regards,
            I did more testing starting from scratch using this procedure and it appears that the baud rate setting is not being set internally and propagated to the Picaso. The .ino file generated shows the baud rate set to 200000 no matter what you set in the Serial options screen. Here is the code generated...

            // now start display as Serial lines should have 'stabilised'
            DisplaySerial.begin(200000) ; // Hardware serial to Display, same as SPE on display is set to
            Display.TimeLimit4D = 5000 ; // 5 second timeout on all commands
            Display.Callback4D = mycallback ;

            Also I found that once the Picaso starts generating errors it never recovers even if I stop the scale from sending data (no power to the motors)
            Attached Files

            Comment


            • #21
              No comments? I guess I'll have to throw this in the trash.It's too buggy to use.

              Comment


              • #22
                Well I can comment a bit immediately, the 4Duino is fixed at 200000 baud, as this is the highest optimal speed for it.

                Doesn't explain why you are getting timeouts, but I think you need to give Noel a bit more time to test and get back to you.

                Not sure where the bugs are but atm they seem to be related to hardware interactions, keep with us so that you might have a chance of resolving them
                Mark

                Comment


                • #23
                  Dear dskogman,

                  Could you please modify the code as below and test it?

                  Code:
                  void read_scale()
                  {
                    // read scale
                    nbytes = mySerial.available();
                  
                    if ( nbytes == 17 ) // complete message // could you please change this to if(nbytes>=17) since the nbytes=mySerial.available may not be able to check if nbytes is equal to 17
                    { // at the right time if the processor is executing the code else where
                      for ( int n = 0; n < 17; n++)
                      {
                        ibuf[n] = mySerial.read();
                      }
                      if (ibuf[15] != 0xD) goto SKIP2;
                      ibuf[15] = 0; // strip CRLF
                      cload[9] = 0;
                      strncpy( cload, &ibuf[3], 9);
                      load = atof( cload );
                      ibuf[3] = 0;
                      strncpy( scale_status, ibuf, 4 );
                      //Display.txt_MoveCursor(2,0);
                      //Display.putstr(ibuf);
                      //Display.txt_MoveCursor(4,0);
                      //Display.print(ibuf);
                      //Display.print(load,2);
                    }
                    else if ( nbytes >= 18 ) // flush buffer
                    {
                      for ( int n = 0; n < nbytes; n++)
                      {
                        char c = mySerial.read();
                      }
                    }
                  SKIP2:
                  
                    return; // <--- the right code should be break to get out of the for loop. The function is void so it wont return a value.
                  }
                  Last edited by James_4DSystems; 24th March 2017, 06:06 AM. Reason: Please use a code box

                  Comment


                  • #24
                    Noel,
                    thanks, I suspected the scale reading may be a problem as well so had already rewritten it as shown below. This improved the scale serial processing but did not fix the errors from the display. I would like to try to slow down the baud rate on the display to see if that helps but their doesn't seem to be any way to reset it as indicated above?
                    Doug

                    edit -> new version that checks for /n then checks the number of characters

                    Code:
                    bool read_scale()
                    {
                      bool found = false;
                    
                      // read scale
                      nbytes = mySerial.available();
                    
                      while ( nbytes > 0 )
                      {
                        ibuf[icnt] = mySerial.read();
                    
                        if (ibuf[icnt] == 0xA) // message terminator = /n
                        {
                          if ( icnt == 16 ) //full message (16 instead of 17 since icnt not incremented yet)
                          {
                            ibuf[15] = 0; // strip CRLF
                            cload[9] = 0;
                            strncpy( cload, &ibuf[3], 9);
                            load = atof( cload );
                            ibuf[3] = 0;
                            strncpy( scale_status, ibuf, 4 );
                            found = true;
                            Display.txt_MoveCursor(1, 20);
                            Display.print(F(" "));
                            icnt = 0;
                          }
                          else //error
                          {
                            Display.txt_MoveCursor(1, 20);
                            Display.print(F("BAD"));
                            Display.txt_MoveCursor(0, 10);
                            ibuf[15] = 0;
                            Display.print( ibuf );
                            nbytes = mySerial.available();
                            for ( int n = 0; n < nbytes; n++) // flush the buffer
                            {
                              mySerial.read();
                            }
                            icnt = 0;
                            goto SKIP2;
                          }
                        }
                        else
                        {
                          icnt++;
                        }
                        nbytes--;
                      }
                    
                    SKIP2:
                      return found;
                    }
                    Last edited by James_4DSystems; 24th March 2017, 06:07 AM. Reason: Please use a code box

                    Comment


                    • #25
                      Dear dskogman,

                      On line 361, please modify if( nbytes == 17 ) to if( nbytes >= 17 ) since if the MCU executes the code nbytes=mySerial.available();, the serial buffer may have incremented greater than 17
                      so the code after if will not execute.

                      Code:
                      Display.txt_MoveCursor(3, 0);
                      Display.print("# grains to fill = ");
                      Display.print(ngrains, 2);
                      //Display.txt_MoveCursor(5,0);
                      //Display.print(" ");
                      do
                      {
                        // read scale
                        nbytes = mySerial.available();
                      
                        if ( nbytes == 17 ) // <---------------------------------- line 361
                        {
                          for ( int n = 0; n < 17; n++)
                          {
                            ibuf[n] = mySerial.read();
                          }
                          if (ibuf[15] != 0xD) goto SKIP;
                          ibuf[15] = 0; // strip CRLF
                          cload[9] = 0;
                          strncpy( cload, &ibuf[3], 9);
                          load = atof( cload );
                          ibuf[3] = 0 ; // strip header
                          //Display.txt_MoveCursor(2,0);
                          //Display.putstr(ibuf);
                      
                          Display.txt_MoveCursor(4, 0);
                          Display.print(ibuf); // print status
                          Display.print(load, 2); // print weight
                          if ( load >= ngrains )
                          {
                            mtr_vib->run(RELEASE); // stop motor
                            mtr_drib->run(RELEASE);
                            pulselen = map(int(pwdr_ipos + pwdr_angle), 0, 100, SERVOMIN, SERVOMAX);
                            pwm.setPWM(pwdr_servo, 0, pulselen);
                            done = true;
                          }
                          else if ( load < 0.3 )
                          {
                            // don't start till trickler starts
                          }
                          else
                      In addition, could you try using one shield at a time and test which shield will cause the error to be reported so we can isolate the code or hardware which causes the error.

                      Best regards,

                      Comment


                      • #26
                        Maybe you didn't see it but I modified the code in post #24 to read the characters and look for the terminator (0xA) instead of a byte count which works better.

                        I removed the shields and rewired the serial port directly to the 4duino with no servos or motors. This seemed to work OK but of course it's not doing much either. I then added the shields back and played around with reducing delays and reading the scale more often to prevent overflows. It runs longer now but still starts generating errors after a while. The screen does update when the errors start but there are errors with each display write once it starts.

                        Comment


                        • #27
                          I can't really offer any concrete help here, but I think I can make a few useful suggestions.
                          Software serial's reliability is severely upset by interrupts, the 4Duino only has the Display's hardware serial interrupts to deal with, but even then software serial is limited to 19200 to get any semblence of reliability.

                          Adding servo.h introduces another level of interrupt and thus I can imagine software serial will be having all sorts of issues trying to read accurate data from the RX pin.

                          So there are a few things to try
                          1. Decrease the baud rate to 9600
                          2. Send the information read from the SF port to the uSB serial to see just how reliable the read data is
                          3. Improve the robustness of the 'Read scale' code, so that it can handle garbage data without getting lost. Some of the versions of the code posted here will have all sorts of issues if the 0x0a is not present due to corruption, some will even cause the array to exceed its bounds
                          4. Add code to 'read scale' to try and align the data being read to the 'start character', (or 0x0a end character) to try and help identification of 'good' data
                          Mark

                          Comment


                          • #28
                            Mark,
                            The read scale code certainly had some issues but the current one works well enough. The scale is updating at 10hz x 17 bytes = 170 bytes/sec which is not a huge load. I added logging code to uSB serial as you suggested and the data is fine. When the servos run there is a 1+ sec delay in reading so it overflows and gets partial data but recovers fine.

                            The issue is not the software serial processing. The issue is the Display serial failing after 5 to 10 minutes and NOT being able to recover. Every write to the display after it starts failing returns an error even when everything else is idle. Software serial continues to run OK even after the Display starts failing.

                            All I can do at this point is a manual reset after it fails and start over.

                            Comment


                            • #29
                              It's not clear how you can be so sure of that. Can you attach your full current code, so I can try and run it?
                              Mark

                              Comment


                              • #30
                                I have attached a log of the debug output. It is every scale reading as well as button events for dumping the pan, running the stepper, running the vibrator, etc.You can see the overflows when the servos/steppers run and the recovery after. At the bottom you can see where the Display starts generating errors.
                                Attached Files

                                Comment

                                Working...
                                X