My C program only works when I open and close serial monitor

Hello everyone, it is my first time using Arduino (uno) for school project and they want a c program to communicate with it via serial, and after I came up with a C code after reading countless docs and tutorials.

The problem is that if I upload code to the Arduino and then try to communicate via c program the RX led blinks but I doesn't do nothing, I have to open the serial monitor on the IDE and close right after and then It works.

I already have read so many other posts with this issue and I suppose the solution was something with DTR and RTS, but after doing that stuff it still does not work...

For now I'm just sending 1 byte, letter 'A', and the c program works fine after opening and closing serial monitor, other thing I noticed is that after that I need to send 'A' two times for it to work, only sending 'A' one time does nothing too.

I appreciate any help,
Thanks

.ino code

#include <SoftwareSerial.h>
#include <HardwareSerial.h>

// Pins
int pinLed0 = LED_BUILTIN;
int pinLed1 = 12;
int pinLed2 = 13;
// Serial stuff
int dataLenght = 1;
char szBuff[2];

void setup() {
  // Put your setup code here, to run once:
  // Initialize serial
  Serial.begin(9600);
  Serial.setTimeout(1000);
  // Initialize the pins as an output
  pinMode(pinLed0, OUTPUT);
  pinMode(pinLed1, OUTPUT);
  pinMode(pinLed2, OUTPUT);
}

void loop() {
  // Put your main code here, to run repeatedly:
  if (Serial.available() > 0) {
    // Read bytes sent
    Serial.readBytes(szBuff, dataLenght);
    // Control led based on data sent
    if (szBuff[0] == 'A') digitalWrite(pinLed1, HIGH); 
    else digitalWrite(pinLed1, LOW);
  }

  digitalWrite(pinLed2, HIGH);
  delay(100);
  digitalWrite(pinLed2, LOW);
  delay(100);
}

.c code

#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <process.h>
#include <fileapi.h>

HANDLE hSerial;
DCB dcbSerialParams;
COMMTIMEOUTS timeouts;
DWORD dwBytesWrite;
int dataLenght = 1;
char szBuff[2];
char readConsole[2];
char lastError[1024];
char bytesWriten[1024];

int main() {
	// Serial handle
	hSerial = CreateFile(L"\\\\.\\COM3", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
	if (hSerial == INVALID_HANDLE_VALUE) {
		if (GetLastError() == ERROR_FILE_NOT_FOUND) {
			printf("!Serial port error, port does not exist.\n"); // Serial port does not exist. Inform user.
		}
		printf("!Serial error has occurred.\n");
	}

	// DCB configuration.
	if (!GetCommState(hSerial, &dcbSerialParams)) {
		printf("!Error getting state.\n"); // Error getting state.
	}

	SecureZeroMemory(&dcbSerialParams, sizeof(DCB));
	dcbSerialParams.DCBlength = sizeof(DCB);

	if (!GetCommState(hSerial, &dcbSerialParams)) {
		printf("!Error getting state.\n"); // Error getting state.
	}

	dcbSerialParams.BaudRate = CBR_9600; // Baud rate
	dcbSerialParams.ByteSize = 8; // Data size, xmit and rcv
	dcbSerialParams.Parity = NOPARITY; // Parity bit
	dcbSerialParams.StopBits = ONESTOPBIT; // Stop bit

	if (!GetCommState(hSerial, &dcbSerialParams)) {
		printf("!Error getting state.\n"); // Error getting state.
	}

	// Setting the DTR to Control_Enable ensures that the Arduino is properly reset upon establishing a connection
	dcbSerialParams.fDtrControl = DTR_CONTROL_ENABLE;
	dcbSerialParams.fRtsControl = RTS_CONTROL_DISABLE;
	dcbSerialParams.fDsrSensitivity = FALSE;

	PurgeComm(hSerial, PURGE_RXCLEAR);
	PurgeComm(hSerial, PURGE_TXCLEAR);
	// We wait 2 seconds as the arduino board will be reseting
	Sleep(2000);
	
	if (!GetCommState(hSerial, &dcbSerialParams)) {
		printf("!Error getting state.\n"); // Error getting state.
	}

	if (!SetCommState(hSerial, &dcbSerialParams)) {
		printf("!Error setting state.\n"); // Error setting state.
	}

	// Timeout configuration.
	timeouts.ReadIntervalTimeout = 1000;
	timeouts.ReadTotalTimeoutConstant = 1000;
	timeouts.ReadTotalTimeoutMultiplier = 1000;
	timeouts.WriteTotalTimeoutConstant = 1000;
	timeouts.WriteTotalTimeoutMultiplier = 1000;
	
	if (!SetCommTimeouts(hSerial, &timeouts)) {
		printf("!Timeout error occurred.\n"); // Timeout error occureed.
	}

	//// OpenCommPort

	while (1) {
		printf("Write A or B\n");
	
		fflush(stdin);
		fflush(stdout);
		gets(&readConsole);
	
		strcpy_s(&szBuff, sizeof(szBuff), readConsole);
		printf("You wrote: %s\n", szBuff);
	
		if (!WriteFile(hSerial, (void*)szBuff, dataLenght, &dwBytesWrite, 0)) {
			printf("!Write error occurred.\n"); // Write error occurred.
		}
	}
	
	CloseHandle(hSerial);
}

can you read/write data using the serial monitor of the Arduino IDE?

Yes, right after uploading, if I open the serial monitor IDE and type 'A' the led turns on.

so what's the problem?
the C program presumably being built/run on a PC?

If I upload the code to the arduino and instead of opening the serial monitor and use C program when typing 'A', the RX led blinks but the led does not turn on.

After that if I close the C program and open serial monitor, then close the serial monitor, then start my C program again, then type 'A' on the C program console, The leds turns on and works just fine.

the Arduino IDE connects to the Arduino using the com port. it uses the com port both to download and communicate (Serial) with the Arduino.

have you tried closing the IDE so that the com port is now available for some other application and then running your C program?

I´ve tried it, same behavior, and I think I read somewhere the IDE only blocks the com port only when Serial monitor or plotter is open.

When I open the serial monitor the leds blink 2 times and then turn off for a bit. is it resetting every time I open the serial monitor?

This does not happen when I upload the code to the arduino and execute the C program, but if I open and close the serial monitor and then execute the C program again, it does that. (and that's when the C program works just fine).

You need to set RTS and DTR LOW, wait 100ms, bring DTR HIGH and wait 100ms.

You mean like this?

	// Setting the DTR to Control_Enable ensures that the Arduino is properly reset upon establishing a connection
	dcbSerialParams.fDtrControl = DTR_CONTROL_DISABLE;
	dcbSerialParams.fRtsControl = RTS_CONTROL_DISABLE;
	Sleep(100);
	dcbSerialParams.fDtrControl = DTR_CONTROL_ENABLE;
	Sleep(100);
	PurgeComm(hSerial, PURGE_RXCLEAR | PURGE_TXCLEAR);
	// We wait 2 seconds as the arduino board will be reseting
	Sleep(2000);

Unfortunately, this didn't fix my issue
If I tell im using visual studio 2022 to make and compile this program does it help? is there any issue with it?

Yes like that
My code is in VB and it works. Don't know about C

Try waiting for a full second. The Arduino program has to be reloaded and if it is dig it takes a while.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.