Go Down

Topic: Hardware Serial and Boot questions (Read 3986 times) previous topic - next topic

giggler

Hi,

I have been playing with Arduino One, R3, has a U16 as comm's to PC.  I have a few questions the reference manual on the API does not cover.

1. When I open the COM port on the PC, does the U8/U16 UART mega device reboot my 328P micro, so it always ends up in Init(...) on PC port open?  I have been using the Serial monitor and noticed it certain does somehow cause a reboot but my own code does not always since some global's are still setup from previous use, suggesting it does not when I open/close the port from C#.

2. If you send data to PC (serial.write(...)) during Init(...), it seems to be echoed back, or there is some data available initially to read by Arduino code on the 328P.  I didn't know this and it kind of screwed up my application, resulting in lots of head scratching.  Can someone confirm that when in Init(...) and no PC is setup to communication via VCOM, the driver in the U8/U16 either echo's back the data you send or sends some other data?  I have not checked what the data is, but noticed it was the same length (time dependant) as the message I sent in Init(...) to PC.  There are certain situations where this could be the cause, like if you close the VCOM port on the PC but the device is still powered via USB cable, ofcouse then it's probably in Loop(...) but you get the idea.

Regards,

dc

PaulS

Quote
1. When I open the COM port on the PC, does the U8/U16 UART mega device reboot my 328P micro, so it always ends up in Init(...) on PC port open?

Unless you've modified the Arduino, yes, the Arduino is reset. It gets through init() very quickly, though.

Quote
I have been using the Serial monitor and noticed it certain does somehow cause a reboot but my own code does not always since some global's are still setup from previous use, suggesting it does not when I open/close the port from C#.

Yes, it does.

Quote
2. If you send data to PC (serial.write(...)) during Init(...), it seems to be echoed back

Not unless that is specific code on the Arduino (that you wrote) to do that.

Quote
I have not checked what the data is, but noticed it was the same length (time dependant) as the message I sent in Init(...) to PC.

You should not be adding code to init(). The first place for you to add code is setup().

giggler

Thanks for your quick response.  Sorry, you are right, it's Setup(...) and Loop(...) I'm talking about.

I have not modified the code myself but since it was preprogrammed when bought it off ebay, I cannot either confirm that standard release code is in the U16.  I assume it is.

Regards,

dc

PaulS

Quote
I have not modified the code myself but since it was preprogrammed when bought it off ebay, I cannot either confirm that standard release code is in the U16.  I assume it is.

The standard sketch that comes loaded on the Arduino is the blink with delay sketch. It does nothing with Serial.

It isn't the end of the world if you overwrite that sketch. You can always restore it.

giggler

I think I've found the issue.  Using Putty, reboots 328P everytime as does Serial Monitor from IDE but my C# program didn't.

Now, *if* you open the port setting RTSEnable=True, and DTREnable=True the micro reboots as expect.  However setting either of these to false, opens the port *without* rebooting the micro.

I tested this with a scope probe on reset line of 328P.  So using what I believe is default U8/U16 firmware, you can open the port without rebooting your micro.  Also some strange behaviour can be seen from the U8/U16 firmware where octets are read that is basically junk.  The odd thing is, it actually all works generally if your protocol handler ignores the junk because they are outside your command specification.

I will post my C# program and firmware in mo.

dc

giggler

Arduino One Test firmware:

#include "arduino.h"

static uint8_t sent=0;
static uint8_t rxdata_ix=1;  // always have 1 octet as length
static uint8_t rxdata[256];

void setup() {
  Serial.begin(115200);
}

void loop() {
  if (sent==0) {
    Serial.println("Booting");
    sent=1;
  }
  delay(10);  // arbitrary delay
  if (Serial.available()) {
    int octet=Serial.read();
   
    if (octet!=-1) {
      if (octet=='r') {  // PC request to read boot octets
        uint8_t i;
         
        // Looping output boot read octets, if any.  Will always output 1 octet, first being length which could be 0
        rxdata[0]=rxdata_ix;  // length octet
        for(i=0;i<rxdata_ix;i++) {
          octet=rxdata;
          // Output octet
          Serial.write(octet);
        } // for(...)
      }else {
        if (rxdata_ix<=254) {
          rxdata[rxdata_ix++]=octet;
        }
      }
    }
  } // if (!Serial.available())
} // loop()


C# PC test code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Ports;
using System.Diagnostics;

namespace StepTestApp
{
    class Program
    {
        [STAThread]
        static void Main(string[] args)
        {
            SerialPort sp = new SerialPort("COM4", 115200, Parity.None, 8, StopBits.One);

            // changing either of these to false causes 328P micro on Arduino one to not reboot, yet the port is opened
            sp.RtsEnable = true;
            sp.DtrEnable = true;

            sp.Handshake = Handshake.None;
            sp.WriteTimeout = SerialPort.InfiniteTimeout;
            sp.ReadTimeout = SerialPort.InfiniteTimeout;
            sp.WriteBufferSize = 2048;
            sp.ReadBufferSize = 2048;

            sp.Open();
            if (!sp.IsOpen)
            {
                System.Console.WriteLine("Error: Port not open");
            }
            else
            {
                System.Console.WriteLine("Port open");

                bool send = true;

                Stopwatch stopwatch = new Stopwatch();
                stopwatch.Start();

                do
                {
                    System.Threading.Thread.Sleep(10);
                    if (sp.BytesToRead > 0)
                    {
                        int octet = sp.ReadByte();

                        if (octet >= 33 && octet < 127)
                        {
                            System.Console.Write("{0} ", (char)octet);
                        }
                        else
                        {
                            System.Console.Write("{0:X2} ", octet);
                            if (octet == 0x0a && send)
                            {
                                System.Console.WriteLine("\n\nSending read command");

                                // send PC read request
                                sp.Write(new byte[] { (byte)'r' }, 0, 1);
                                send = false;
                            }
                        }
                    }
                    else if (send)
                    {
                        TimeSpan t=stopwatch.Elapsed;

                        if (t.Seconds >= 8)
                        {
                            System.Console.WriteLine("\n\nSending read command");

                            // send PC read request
                            sp.Write(new byte[] { (byte)'r' }, 0, 1);

                            stopwatch.Stop();

                            send = false;
                        }
                    }
                } while (true);
            }
        }
    }
}

retrolefty

That is not how to post code on this forum. There is a "#" button above the edit window that will allow you to insert code into it's own window.

Lefty

PaulS

There is a sticky at the top of the forum defining how to post a question in this forum. You get failing marks for not having read it.

giggler

Just to recap, the reason for posting here is because my firmware reads crap from USART *if not rebooted* but still seems to function.  That caused a lot of head scratching.

In C#

COM line controls.

sp.RtsEnable = true;
sp.DtrEnable = true;

Results in working firmware with reboot everytime.

But either or both as false

sp.RtsEnable = false;
sp.DtrEnable = false;

Results in working firmware (flacky) with NO reboot.  On the PC the COM port opens successfully with both settings, however the responses between firmware and PC differ.

When both line control flags are true, console output, always:

Port open
B o o t i n g 0D 0A

Sending read command
01

The 01 is reply from firmware, indicating there is only 1 octet to read from firmware.  This is a length field, so basically no USART data was read by firmware.  It displays octets captured by USART in firmware prior to command invoke.  If you open putty and type stuff, pressing lower case 'r' will repeat everything until 255 characters.


Now setting either line control flag to false, results in:

Port open


Sending read command
07 F0 F0 F0 F0 F0 F0

and run again:

Port open


Sending read command
0B F0 F0 F0 F0 F0 F0 F0 F0 F0 F0


and run again:

Port open


Sending read command
0F F0 F0 F0 F0 F0 F0 F0 F0 F0 F0 F0 F0 F0 F0

etc.

The point to make here is the USART is reading those F0 hex figures at some point and they certainly arn't sent from PC.  These have been making my simple protocol in firmware malfunction.  Now I know, I can fix by changing the way I open the PC port but I feel this is certainly something I'd consider a bug in the CDC implementation of the U8/U16 firmware.

If not a bug, I feel to save the same headache from other developers, it should at least be mentioned in the reference material since that what most people work from.

What do you chaps think?

Regards

dc

giggler

Code: [Select]


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Ports;
using System.Diagnostics;

namespace StepTestApp
{
    class Program
    {
        [STAThread]
        static void Main(string[] args)
        {
            SerialPort sp = new SerialPort("COM4", 115200, Parity.None, 8, StopBits.One);

            // changing either of these to false causes 328P micro on Arduino one to not reboot, yet the port is opened
            sp.RtsEnable = false;
            sp.DtrEnable = false;

            sp.Handshake = Handshake.None;
            sp.WriteTimeout = SerialPort.InfiniteTimeout;
            sp.ReadTimeout = SerialPort.InfiniteTimeout;
            sp.WriteBufferSize = 2048;
            sp.ReadBufferSize = 2048;

            sp.Open();
            if (!sp.IsOpen)
            {
                System.Console.WriteLine("Error: Port not open");
            }
            else
            {
                System.Console.WriteLine("Port open");

                bool send = true;

                Stopwatch stopwatch = new Stopwatch();
                stopwatch.Start();

                do
                {
                    System.Threading.Thread.Sleep(10);
                    if (sp.BytesToRead > 0)
                    {
                        int octet = sp.ReadByte();

                        if (octet >= 33 && octet < 127)
                        {
                            System.Console.Write("{0} ", (char)octet);
                        }
                        else
                        {
                            System.Console.Write("{0:X2} ", octet);
                            if (octet == 0x0a && send)
                            {
                                System.Console.WriteLine("\n\nSending read command");

                                // send PC read request
                                sp.Write(new byte[] { (byte)'r' }, 0, 1);
                                send = false;
                            }
                        }
                    }
                    else if (send)
                    {
                        TimeSpan t=stopwatch.Elapsed;

                        if (t.Seconds >= 8)
                        {
                            System.Console.WriteLine("\n\nSending read command");

                            // send PC read request
                            sp.Write(new byte[] { (byte)'r' }, 0, 1);

                            stopwatch.Stop();

                            send = false;
                        }
                    }
                } while (true);
            }
        }
    }
}

#include "arduino.h"

static uint8_t sent=0;
static uint8_t rxdata_ix=1;  // always have 1 octet as length
static uint8_t rxdata[256];

void setup() {
  Serial.begin(115200);
}

void loop() {
  if (sent==0) {
    Serial.println("Booting");
    sent=1;
  }
  delay(10);  // arbitrary delay
  if (Serial.available()) {
    int octet=Serial.read();
   
    if (octet!=-1) {
      if (octet=='r') {  // PC request to read boot octets
        uint8_t i;
         
        // Looping output boot read octets, if any.  Will always output 1 octet, first being length which could be 0
        rxdata[0]=rxdata_ix;  // length octet
        for(i=0;i<rxdata_ix;i++) {
          octet=rxdata[i];
          // Output octet[i]
          Serial.write(octet);
        } // for(...)
      }else {
        if (rxdata_ix<=254) {
          rxdata[rxdata_ix++]=octet;
        }
      }
    }
  } // if (!Serial.available())
} // loop()



Blah...

Go Up