I have a motor that is connected to an Arduino and this Arduino is connected to Raspberry Pi. Rapberry Pi is running my Phoenix app.
Arduino is programmed to receive serial input and uses this input as steps
to rotate the motor.
I am using GitHub - elixir-circuits/circuits_uart: Discover and use UARTs and serial ports in Elixir
and in the iex session when run the following command, I am able to rotate the motor for 100 steps.
{:ok, pid} = Nerves.UART.start_link(name: :motor1)
:ok = Nerves.UART.open(pid, "ttyACM0", speed: 9600, active: false)
:ok = Nerves.UART.write(pid, "1000")
However, if I use the same code in Phoenix controller, the motor doesn’t rotate. Neither do I get any error.
Is there anything specific that I need to take care of when calling Phoenix controller?
Thanks for any help.
You shouldn’t be start_link’ing in a controller I’d think. Shouldn’t that be part of your supervisor tree?
@OvermindDL1, yes right. I kept it simple for discussion on the forum and not to distract with the details of implementations.
The way I have configured it on my actual application is by using a named process.
children = [
....
worker(Nerves.UART, [[name: :motor]])
]
and then in the controller, I am retrieving the process by name.
pid = GenServer.whereis(:motor)
:ok = Nerves.UART.open(pid, "ttyACM0", speed: 9600, active: false)
:ok = Nerves.UART.write(pid, "1000")
Nerves.UART.close(pid) # I tried with/without this line.
Does this setup sound ok?
If I run above code in controller in an iex -S mix
session, I am able to move the motor for 1000 steps. However, it doesn’t work when triggered from the controller.
Does the string that you write need a termination character line a “\n” or something like that? I’m wondering how the Arduino knows that you’re done sending it data. I can’t explain how this worked at the IEx prompt, though. You didn’t have line framing on, did you?
Not your problem, but it’s common to wrap the use of Nerves.UART
in a module so that you can say things like Motor.forward(1000)
in your controller code. This also lets you keep the UART open between calls rather than opening and closing it. I assume that your calls are pretty low frequency, but the close operation on some serial port drivers is asynchronous. I’ve had opens fail due to the serial port being momentarily busy. If you ever need to receive notification messages from the Arduino, you’ll want to keep the port open at all times to avoid losing anything anyway.
1 Like