Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RTS being set high on port connection #195

Open
Faller9249 opened this issue Sep 1, 2023 · 5 comments
Open

RTS being set high on port connection #195

Faller9249 opened this issue Sep 1, 2023 · 5 comments

Comments

@Faller9249
Copy link

I'm using the API to make a connection with a UART to USB adapter, the CP2102, and everytime I make a fresh connection with it, by fresh I mean disconnecting the USB cable entirely, the RTS(Request To Send) pin gets set high, even with flowcontrol disabled(set to 'none'), and that is a very big problem for me as the RTS pin of the chip is being used for a very important purpose and this kind of behavior isn't very suited for our application. The code for the actual application is proprietary to the company I work at, but below is a simple code that has the same problem.

<div class="serial-scale-div">
	<button class="btn" id="connect-to-serial" onclick="init()">Connect with Serial Device</button>
</div>
<select id="baudrate">
  <option>9600</option>
  <option>19200</option>
  <option>38400</option>
  <option>57600</option>
  <option>115200</option>
  <option>230400</option>
  <option>460800</option>
  <option>500000</option>
  <option>921600</option>
  <option>1000000</option>
</select>
<button id="get-serial-messages">Get serial messages</button>

<div id="serial-messages-container">
	<div class="message"></div>
</div>

<script>
"use strict";
const connect = document.getElementById('connect-to-serial');
const getSerialMessages = document.getElementById('get-serial-messages');
var port=null;
var reader=null;

getSerialMessages.addEventListener('pointerdown', async () => {
  getSerialMessage();
});


async function getSerialMessage() {
	document.querySelector("#serial-messages-container .message").innerText += await serialScaleController.read();		  
}

async function init() {
	console.log("iniciando");
	if ('serial' in navigator) {
		try {
			if (port){
				port.close();
				reader.releaseLock();
			}
			console.log(navigator.serial);
			port = await navigator.serial.requestPort();
			console.log(document.getElementById("baudrate").value);
			await port.open({ baudRate: parseInt(document.getElementById("baudrate").value)});
			let decoder = new TextDecoderStream();
			port.readable.pipeTo(decoder.writable);
			const inputStream = decoder.readable;
			reader = inputStream.getReader();
			let signals = await port.getSignals();
			console.log(signals);
			readLoop();
		}
		catch (err) {
			console.error('There was an error opening the serial port:', err);
		}
	}
	else {
		console.error('Web serial doesn\'t seem to be enabled in your browser. Try enabling it by visiting:');
		console.error('chrome://flags/#enable-experimental-web-platform-features');
		console.error('opera://flags/#enable-experimental-web-platform-features');
		console.error('edge://flags/#enable-experimental-web-platform-features');
	}
}

async function readLoop(){
	while (port.readable) {
		const { value, done } = await reader.read();
		document.getElementById("serial-messages-container").innerHTML += value;
		// Do something with |value|...
    }
}
</script>

I've tested a couple of things already:

  • calling the setSignals() method before and after the open() method
  • calling the setSignals() method with requestToSend as true and false, dataTerminalReady as well just to be sure
  • setting flowcontrol to 'none' and to 'hardware'
  • making the code synchronous instead of asynchronous

I don't know if I'm missing some critical piece of code or if I'm using something wrong. I've even tried reading the Blink implementation C code to try and understand if there was a problem in the abstraction layers or something like that.

@reillyeon
Copy link
Collaborator

Assuming you are on Windows then the code in SerialIoHandlerWin::ConfigurePortImpl() is relevant here. If hardware flow control is disabled then the DCB structure is configured with both RTS_CONTROL_ENABLE and DTR_CONTROL_ENABLE. This means the default state of these two control signals is high.

It should be possible to lower them after opening the port with setSignals({ dataTerminalReady: false, requestToSend: false }) but this isn't helpful if the device responds poorly to any high state of the RTS line. Have you been able to lower the RTS signal in this way? It isn't clear from your report.

The two solutions to fix this at an API level would be to support calling setSignals() before open(), or add signals property to the options dictionary which can include dataTerminalReady and requestToSend options. We will need to check that the macOS and Linux implementations are also capable of setting the initial value of these signals the way the Windows implementation is.

@Faller9249
Copy link
Author

About the second paragraph, I did test setting it right after the open method, but as you said, our device is affected by any alteration in the RTS line. What you suggested in the third paragraph would be ideal, as we have tested with the electron-serialport library on node.js running locally and if we had a way to set the RTS upon opening the port, that would be perfect. But my main concern with an API level change would be whether or not this change would be easy to dissipate for users of our application.

@reillyeon
Copy link
Collaborator

An API-level change would need to be specified and implemented before it could roll out to your users. Unfortunately it seems like there isn't any workaround given the current API design.

@Faller9249
Copy link
Author

Do you if there is another option of API or is this one really the only one we can use on web browsers? I know the answer is probably no, but we really needed to solve this ASAP.

@reillyeon
Copy link
Collaborator

After doing a bit more research it looks like setting the initial RTS and DTR state is only supported on Windows. macOS and Linux systems will always assert these pins when the port is opened. At best this means that if we implemented the option to control the signal state when the port is opened the lines would flash briefly into the high state before being reset during initial port configuration.

I recommend working with your hardware vendor to not reuse the RTS line for an unintended purpose.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants