disable auto-reset by serial connection

hey all,
we have a use-case for Arduino, where we have to avoid the auto-reset feature of the Diecimila boards.
It's because the Arduino is already running, controlling startup und shutdown of the host PC. This is no problem with the NG boards, but with the Diecimila, the status of the Arduino is lost because it resets as soon as the host PC is booting and the USB connection is established.

Is there a way to modify (hardware or bootloader of) the Diecimila so that it does NOT auto-reset on a serial connection?

many thanks,
Thomas

The board is reset by the Serial port DTR line going low and pulsing the Arduino reset pin. You can prevent this if you can disable DTR on your PC or by removing the capacitor that connects the DTR Serial pin to the reset pin.

There is a hardware solution: to remove the 100nF cap (I think it's labeled as R3). Since the cap is smd type, depending on your soldering equipment and skil, this change will make some ruin on board.

I saw some discussion about software solution, but I don't know where, and I don't remember if it was sucessful.

Or you can communicate via a separate USB-to-serial converter connected to pins 0 and 1 of the Arduino board.

Hi,

I have researched this issue a bit on Linux and Windows. I have been able to get a client program (written in C++) to connect and disconnect to my Arduino Diecimila without causing a reset.

The solution lies in proper setup of the serial connection, and requires no extra hardware or hardware modification. You hust have to disable HUPCL on linux and DTR on Windows

On Linux you typically call tcsetattr
Before you call it you set

termios mode;
::memset(&mode,0,sizeof( mode));
tcgetattr(m_fd,& mode);
... other settings here
mode.c_cflag &= ~HUPCL; // disable hang-up-on-close to avoid reset
tcsetattr(m_fd,TCSANOW,&mode)

On Windows

DCB dcb;
GetCommState(m_hCom, &dcb);
... other settings here
dcb.fDtrControl = DTR_CONTROL_DISABLE; // disable DTR to avoid reset
SetCommState(m_hCom, &dcb);
Then do NOT call EscapeCommFunction(...) or anything like that to set DTR later

With these settings I have it working for both Windows and Linux, I can connect as many times as I wish without causing a reset of the board.

1 Like

so this code will work with the usb diecimila? i have problem where the arduino is being powered via battery and when i plug in the usb to collect data from the sram the board resets and i loose all my data :frowning:

if not will removing those r2 and r3 on the board work. I would like to avoid this....

thanks

so this code will work with the usb diecimila? i have problem where the arduino is being powered via battery and when i plug in the usb to collect data from the sram the board resets and i loose all my data :frowning:

if not will removing those r2 and r3 on the board work. I would like to avoid this....
thanks

Yes it is the USB Diecimila. I have only been using it USB powered though. The code works for connecting several timed to the Diecimila over USB/Serial from the same or different PC program, without causing a board reset. I don't know if it would be a problem to power from battery and connect/disconnect USB cable like you say.

so this code will work with the usb diecimila? i have problem where the arduino is being powered via battery and when i plug in the usb to collect data from the sram the board resets and i loose all my data :frowning:

if not will removing those r2 and r3 on the board work. I would like to avoid this....
thanks

Yes it is the USB Diecimila. I have only been using it USB powered though. The code works for connecting several timed to the Diecimila over USB/Serial from the same or different PC program, without causing a board reset. I don't know if it would be a problem to power from battery and connect/disconnect USB cable like you say.

I need to know where to put that code (i.e. I'm assuming it goes into the serial client program..... any chance of getting the full source code?)

Thanks again!

[quote author=cacb

I need to know where to put that code (i.e. I'm assuming it goes into the serial client program..... any chance of getting the full source code?)

Thanks again!

Yes, that code goes into the serial client program running on the PC. Below is a link to a couple of serial port C++ classes I have made for communicating over serial ports on Windows and Linux. That code includes the stuff I mentioned above.

http://arnholm.org/arduino/wxSerPort_20080519.zip

These classes are using the http://www.wxwidgets.org/ library. Essentially instantiate a serial port object using wxSerPort::construct(...) and use the set_hupcl member function to enable/disable "hang-up on close" with the Arduino.

on the newest boards (cant remember name the ones without the power jumper) there is a track near the usb port and it has 2 solder pads if you cut the track between these pads the board wont reset and you can solder it back together later

Also with just the right sized resistor as a jumper it is possible to prevent serial resets:

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1213719666/28#28

Fantastic took me ages searching to find the solution but this worked thanks to : cacb for the post above:

My full C++ code to send 7 characters of user input to the board without resetting it was as follows:

// SensorWebPC.cpp
// Pass the port name in the command line - e.g. sensorwebpc comm2
// Original code from sensorwebpc
// code slightly modified by Z Coldrick 18-Jun-2010

#include "stdio.h"
#include <windows.h>
#include <iostream>

using namespace std;

void PrintError( LPCSTR str)
{
LPVOID lpMessageBuffer;
int error = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
error,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), //The user default language
(LPTSTR) &lpMessageBuffer,
0,
NULL
);
printf("%s: (%d) %s\n\n",str,error,lpMessageBuffer);
LocalFree( lpMessageBuffer );
}

int main(int argc, char* argv[])
{
// open port for I/O
HANDLE h = CreateFile("com4",
GENERIC_READ|GENERIC_WRITE,
0,NULL,
OPEN_EXISTING,0,NULL); // my adruino on com4 but this value can be read from argv

if(h == INVALID_HANDLE_VALUE) {
PrintError("E012_Failed to open port");
} else {
// set timeouts
COMMTIMEOUTS cto = { 1, 100, 1000, 0, 0 };
DCB dcb;
if(!SetCommTimeouts(h,&cto))
PrintError("E013_SetCommTimeouts failed");

// set DCB
memset(&dcb,0,sizeof(dcb));
dcb.DCBlength = sizeof(dcb);
dcb.BaudRate = 9600;
dcb.fBinary = 1;
dcb.fDtrControl = DTR_CONTROL_ENABLE;
dcb.fRtsControl = RTS_CONTROL_ENABLE;
dcb.fOutxCtsFlow = 1;
dcb.fRtsControl = DTR_CONTROL_HANDSHAKE;
dcb.fDtrControl = DTR_CONTROL_DISABLE; // avoid reset of arduino board
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;
dcb.ByteSize = 8;

if(!SetCommState(h,&dcb))
PrintError("E014_SetCommState failed");

char buf[8] = "";
cout << "Enter upto 7 characters to send : ";
cin.getline(buf, 8);

DWORD write = 8; // Number of bytes to write to serial port

WriteFile(h,buf,write,&write,NULL); // write is updated with the number of bytes written

DWORD i;
for (i=0; i<write; i++)
{cout << buf[i]; // repeat written chars back in console
}

CloseHandle(h);

}

return 0;
}

This C++ code can be easily compiled with the MinGw/ g++ compiler set to create a stand-alone console app.

(On windows OS)

Ok so now I have encountered a new problem:

My above code works fine to write to the arduino serial com port however I can seem to read from it:

I've tried adding the following code below before I close the handle but with no joy.

DWORD read = 0;
ReadFile(h,buf,sizeof(buf),&read,NULL); // read is updated with the number of bytes read
for (i=0; i<read; i++)
cout << (unsigned char)buf[i];

Any ideas?

Once I have a full solution I will post it on my webpage:

http://www.personal.leeds.ac.uk/~chmzc/

And for anyone using a Arduino that has physical serial connection like the Mini Pro or breadboard Arduino's you can make a connector bridge that doesn't include the DTR pin and it will work without resetting.

The easiest way is to stick a larger value capacitor between gnd and the reset pin. I use a 10uF - works a treat. It has the effect of 'swallowing' the small ground pulse transferred by the 0.1uF auto reset capacitor and preventing the board from resetting. It avoids the current drain of holding it high with a resistor. too.

Auto-reset can be avoided by disabling DTR signal on openingport (on Windows environment):

Connect your source to Microsoft Comm Control (MSCOMM32.OCX) , then:

Dim MSComm1 As Object

Sub ArduinoOpen()
Set MSComm1 = CreateObject("MSCOMMLib.MSComm")
MSComm1.Settings = "9600,n,8,1"
MSComm1.CommPort = 4
MSComm1.InBufferCount = 0
** MSComm1.DTREnable = False**
MSComm1.PortOpen = True
If Err Then
MsgBox "COM" & MSComm1.CommPort & ": not opened, Sorry!"
Exit Sub
End If
End Sub

Sub ArduinoClose()
MSComm1.PortOpen = False
Set MSComm1 = Nothing
End Sub

Tested on ArduinoUno.

Can this info be added to Arduino FAQ?