elixir-circuits / circuits_uart

Discover and use UARTs and serial ports in Elixir
Apache License 2.0
189 stars 48 forks source link

No response on Windows talking to Arduino-board #6

Closed royveshovda closed 8 years ago

royveshovda commented 8 years ago

When running this code on a Windows box (both 10 and 8.1):

{:ok, pid} = Nerves.UART.start_link
:ok = Nerves.UART.open(pid, port_name, speed: 9600, active: false)
Nerves.UART.write(pid, "test\n")
:timer.sleep(500)
Nerves.UART.read(pid)

I do not get anything back. The Arduino is set up to echo the data back:

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

void loop() {  
  if(Serial.available() > 0)
  {
    String data = Serial.readStringUntil('\n');
    Serial.print(data);
    Serial.print("\n");
  }
}

The code is working using the same board on OSX as expected, but no response on Windows (tried on both 10 and 8.1). Tried on two different Arduino boards: Adafruit Feather M0 (SAMD) and Adafruit Feather 32u4

Versions: Elixir 1.3 Erlang: 18.2 Nerves_UART: 0.0.7

Also tried using active-mode, but no response back

fhunleth commented 8 years ago

I was able to reproduce this issue on an Arduino Leonardo. Interestingly running the program on an Arduino UNO doesn't reproduce the problem.

I created a partial fix in https://github.com/nerves-project/nerves_uart/tree/windows. Could you try that branch? The second half was to add flow_control: :software to the configuration options. My line looks like this: :ok = Nerves.UART.open(pid, "COM5", speed: 9600, active: false, flow_control: :software)

It's late for me now and the changes that I made don't make complete sense. It is, however, how I saw that other terminal programs were accessing the Leonardo. I'd like to review the Arduino code to understand why enabling software flow control helped, and I would be curious if these changes fix the issue that you're seeing.

royveshovda commented 8 years ago

That brach worked for me too. On both boards. Nice!

However I am having trouble getting this to work in passive mode, for some strange reason. In active mode I get the response I am suspecting. In passive mode I get {:error, :einval} back from read, but nothing when I call flush. I guess this is not a related subject, so I can open another issue if you want.

fhunleth commented 8 years ago

This is very odd. Unfortunately, both active and passive mode are working for me on the Arduino Leonardo, so I'm not able to reproduce now. :(

Just in case I misunderstood, in passive mode (active: false), read/1 should work. Messages aren't sent, so you won't get anything when you call flush. Active mode sends everything via messages and read/ returns error. I think that you meant to say active mode didn't work or at least that's the way I understood it.

royveshovda commented 8 years ago

Ah, sorry if I expressed myself a bit unclear. I only got active=true to work (calling flush). When I set active=false and call read/1, I get :einval back. Just in case, I called flush in passive mode, but empty.

fhunleth commented 8 years ago

Got it. I think that setting active mode to false is somehow not taking effect for you. If you get :einval back from read, you're still in active mode. Could you post a log of your iex session? I can run what you wrote in the bug report at the very top exactly and that's in passive mode.

royveshovda commented 8 years ago

Sorry for the delay. Here is my iex session (including another small bug):

iex(1)> {:ok, pid} = Nerves.UART.start_link
{:ok, #PID<0.115.0>}
iex(2)> :ok = Nerves.UART.open(pid, "COM3", speed: 9600, active: false, flow_control: :software)
:ok
iex(3)> Nerves.UART.write(pid, "test")
:ok
iex(4)> Nerves.UART.read(pid)
{:error, :einval}
iex(5)> flush
:ok
iex(6)> Nerves.Uart.close(pid)

08:08:28.485 [error] Loading of c:/src/nerves_uart-windows/_build/dev/lib/nerves_uart/ebin/Elixir.Nerves.Ua
rt.beam failed: :badfile

08:08:28.485 [error] beam/beam_load.c(1278): Error loading module 'Elixir.Nerves.Uart':
  module name in object code is Elixir.Nerves.UART

08:08:28.485 [error] Loading of c:/src/nerves_uart-windows/_build/dev/lib/nerves_uart/ebin/Elixir.Nerves.Ua
rt.beam failed: :badfile

08:08:28.486 [error] beam/beam_load.c(1278): Error loading module 'Elixir.Nerves.Uart':
  module name in object code is Elixir.Nerves.UART

** (UndefinedFunctionError) function Nerves.Uart.close/1 is undefined (module Nerves.Uart is not available)
    Nerves.Uart.close(#PID<0.115.0>)
iex(6)> :ok = Nerves.UART.open(pid, "COM3", speed: 9600, active: true, flow_control: :software)
:ok
iex(7)> Nerves.UART.write(pid, "test")
:ok
iex(8)> flush
{:nerves_uart, "COM3", "test\n"}
:ok
iex(9)>
fhunleth commented 8 years ago

No worries - I really appreciate that you're putting in time to debug this.

Regarding the capitalization issue, I'm not sure what to do about that. I believe that's due to Windows having a case insensitive filesystem. Erlang is successful in loading the .beam file, but then it can't find the right module name and everything gets ugly.

Regarding the main problem, I made a couple updates to the windows branch. Could you update your version of nerves_uart to get them? Then, in the Makefile, there's a line to comment in to enable debug logging. Enable that line and rebuild. After that, try the passive mode test and exit iex. With any luck, the file nerves_uart.log will say what's wrong.

royveshovda commented 8 years ago

I will not be able to test this in a while. Just after opening this issue I left for holiday, and did not bring anything running Windows. I will test as soon as I get back, and let you know. Sorry for the delay.

fhunleth commented 8 years ago

No worries, and thanks for the update. I'll merge the RTS fix, since it seems like a good change regardless. We can resume when you get back and settled. Enjoy your time off!

royveshovda commented 8 years ago

I finally got back to my Windows machine (not that I missed it), and got to run the test again after I got the latest commits in the Windows-branch. The result is the same: Active mode is OK, passive mode is not. I attached two different log-files from a very short session, and one longer (which gave me some data back). I hope the log-files makes sense to you.

nerves_uart_longer_session.txt nerves_uart_short_session.txt

fhunleth commented 8 years ago

Thanks for the logs. I likely won't have a chance to look into Windows until after ElixirConf US, but I still really want this issue fixed, so thanks for getting back on it.

fhunleth commented 8 years ago

I believe that I fixed the issue that you had in the logs in commit 21997f14208728d021d3c2c35e5b580a380deb03. This was by accident. I was using the com0com device driver on Windows and found out that it liked to return that a read or write completed synchronously rather than asynchronously when using overlapped I/O. I was under the impression that that wasn't supposed to happen, but the good news is that my logs looked very similar to yours. I don't know why it is different from the other serial device drivers I've used, but who knows. I hope that this fixes the issue for you.

Also, sorry to stash the fix in a branch, but that's where I'm working at the moment. That change should apply cleanly as a patch to the latest nerves_uart release.

fhunleth commented 8 years ago

The fix is now in the v0.1.0 release, and it's up on hex.pm too. I hope this fixes your issue. No rush in confirming. I'll leave this issue open just in case.

royveshovda commented 8 years ago

I can confirm this is working for me too. Great work! I tested the same without flowcontrol: :software too, and it still worked.

Closing the issue

fhunleth commented 8 years ago

Great! Thanks for confirming the fix, and I'm quite happy that flowcontrol: :software is no longer needed since I never understood why that did anything.