1

I use an Arduino Nano with some sensors and send data to a PC using the serial port. I just got a new Arduino Nano 33 BLE and tried the same code but its not working. So for testing I just wrote some simple test code on the Arduino Nano 33 BLE side:

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

void loop()
{
  if (Serial.available())
  {
    char c = Serial.read();
    Serial.write(c);
  }
}

This just sends back whatever arrives through the COM port. Using the Arduino IDE Serial Monitor this works very well with the Arduino Nano 33 BLE. I also made this very simple C# test code (Windows Forms app):

SerialPort serialPort = new SerialPort("COM17", 57600);
serialPort.ReadTimeout = 4000;
serialPort.WriteTimeout = 4000;
serialPort.Encoding = Encoding.ASCII;
serialPort.DataReceived += SerialPort_DataReceived;
serialPort.Open();
if (serialPort.IsOpen)
{
    Debug.Print("COM port open");
}

This C# code works perfect with my good old Arduino Nano but it doesn't work with the Arduino Nano 33 BLE. I have the COM port open message so the port exists and it is open, but then nothing else, no timeout, nothing. I already lost one day trying out all sorts of combinations but it just doesn't work, my C# app can't communicate with the Arduino Nano 33 BLE. It looks like a serial port issue so I think I'll put it on hold for now...

EDIT: The rest of my test code, for reference:

private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    try
    {
        Debug.Print(serialPort.ReadExisting());
    }
    catch (Exception exception)
    {
        Debug.Print(exception.Message);
    }
}

private void buttonSend_Click(object sender, EventArgs e)
{
    try
    {
        serialPort.WriteLine("HELLO");
    }
    catch (Exception exception)
    {
        Debug.Print(exception.Message);
    }
}
7
  • 1
    I'm no expert in C#, but I don't see you actually sending anthing. And where is SerialPort_DataReceived defined?
    – chrisl
    Commented Dec 27, 2022 at 13:20
  • I only copy/past the essential code... but its there... gonna edit the question and add them Commented Dec 27, 2022 at 19:03
  • Have you actually made sure (for example through a debug message), that serialPort.WriteLine("HELLO"); is actually executed? From what you described the problem is in your C# app, not in the Arduino part
    – chrisl
    Commented Dec 27, 2022 at 19:17
  • Using the Arduino IDE Serial Monitor this works very well with the Arduino Nano 33 BLE ... that means that the data is getting to your computer ... what you do with the data after it gets there is off topic here
    – jsotola
    Commented Dec 27, 2022 at 19:33
  • As I also mention in my question, this C# code works fine with an Arduino Nano, so I'm sure the C# code is working. It just doesn't work with the new Arduino Nano 33 BLE. Probably something to do with he mbed layer... but it doesn't make sense, working with Arduino IDE Serial Monitor and not with a C# compiled app. I also read somewhere that the Arduino Nano 33 BLE USB serial port is virtual, so it is a pure software serial port and not a hardware conversion from serial to USB. Commented Dec 27, 2022 at 19:57

1 Answer 1

4

I noticed that a lot of line discipline and flow control settings were not made explicit in your C# code, so it made me wonder what they were by default.

In particular DtrEnable appears to be false by default and Handshake is None by default (which seems to be irrelevant). The other default amount to 8N1. The first part I found interesting because it seems more typical in serial APIs for DTR to be automatically asserted when a port is opened when you're not explicitly asking it to. If I'm reading the .NET documentation correctly, it isn't for your application. The original Nano doesn't much care about DTR apart from a falling edge triggering reset. The board is happy to communicate with it solidly either asserted or not. The original Nano's DTR is only capacitively coupled to reset; there's not a way for the code running on the AVR to respond to DTR (unless you count resetting). That lead to a question about to what extent a Nano 33 BLE would care about DTR.

As it turns out the Nano BLE does care. If I deassert DTR in test with pyserial the board stops sending traffic back. I can write while it's deasserted and after asserting again some queued data arrives. A test environment with pyserial is just more immediately available to me; if needed and I get a chance I'll set up a .net/C# test and confirm with that, but I suspect that won't be necessary. Seeing that result, I searched and found this Arduino Forum post with a somewhat similar problem description. The OP replies in answer to their own post saying:

Problem sorted out. Arduino nano BLE requires DTR and RTS signals to be On. Then it works like FDTI.

Disabling RTS had no effect during my tests with pyserial. I'm not sure why it would. Perhaps they just asserted it preemptively. Being entirely a virtual port RTS doesn't really make sense for flow control. DTR might arguably still makes more sense in this context; at the level of serial signals it normally tells you something is paying attention on the other side of the connection. I'm not really surprised, either way, that the BLE sense would react to DTR being disabled by not sending data to the host; there's a lot of latitude in how these signals can be handled. That it's not automatically used when the port is opened (or until specifically requested) seems mostly a C# thing. But it looks like the different handling of DTR between the two boards that is making your code work with one but not the other.

So it would seem necessary and sufficient to add

serialPort.DtrEnable = true;

amongst your other settings following the opening of the port.

If there's truth to what the Arduino Forum poster said about RTS, then you would also need

serialPort.RtsEnable = true;

but this is not indicated by the tests I've done (though again with pyserial).

3
  • Tx @timemage, you saved my day... hell you saved my week! Yes I confirm that just adding DtrEnable = true does the trick. What the hell were they thinking about? This is a damn virtual port where you don't even have to specify the baud rate! And they care about the DTR signal state? Something that you normally leave unconnected in a hardware serial port? cheeeze... Commented Dec 28, 2022 at 11:40
  • 1
    I think get your frustration. But, to be clear with respect to it being virtual: the host computer doesn't know whether logical requests for changes in baud or DTR result in real world changes to signal levels and timing or that they just terminate the USB stack. From .NET's perspective, it doesn't even know the Serial API is being backed by USB peripheral and not an old style serial port.There's a long tradition of hijacking serial signals for purposes that you'd never guess based on their names.
    – timemage
    Commented Dec 28, 2022 at 14:08
  • 1
    A 1200 baud request together with DTR (and also RTS in the case of the Due and common ESP32/ESP8266 boards) are used in many Arduino type boards both only in the USB stack (where no actual DTR signal or uart timing exists) and also via transceivers to cause entry into bootloaders, to operate chip erasure, etc. I didn't have a specific reason (until testing) to think that the BLE would care (or not) at non-1200 baud (imaginary baud) rates. To the extent that I'm mildly surprised by anything here, it's in the default behaviour of .NET's SerialPort API.
    – timemage
    Commented Dec 28, 2022 at 14:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.