@@ -0,0 +1,293 @@ | |||
LoRa Irrigation System | |||
====================== | |||
This project is to build an irrigation system from LoRa capable | |||
microcontrollers. The [Heltec Node151](https://heltec.org/project/lora-node-151/) | |||
was chosen due to it's small size and inexpensive cost. | |||
Design Decisions | |||
---------------- | |||
While investigating this project, the LoraWAN protocol was investigated, | |||
but after looking at the code complexity and other operational | |||
requirements, if was decided that for this project, it was safer to | |||
target a direct Node to Node style communication system. This would | |||
allow the implementation to be more simple, and security to be built in | |||
(LoRaWAN does have a crypto layer, BUT, trusting/auditing it and any | |||
library that implements it would be a larger task than I want to | |||
undertake). It could also be used for other projects that need | |||
security. | |||
One of the other requirements is that the code be 100% open sourced, | |||
not GPL licensed, and no proprietary components. This meant that using | |||
IDE's like ST's STM32CubeIDE which is only available in binary form | |||
was not a choice, as that would preclude building on an operating | |||
system other than Windows/MacOSX/Linux. | |||
Architecture | |||
------------ | |||
There are a number of components to make this system work. The overall | |||
flow is: | |||
<!-- If using MarkDeep, remove the triple backticks from this and the diagram below --> | |||
``` | |||
************************************************************************************************ | |||
* * | |||
* +---------+ +-------------+ +-------------+ +--------------+ * | |||
* | lora.py | multicast | loraserv.py | USB VCP | lora.gw.elf | LoRa | lora.irr.elf | * | |||
* | +--------------+ +------------+ main.c +---------+ irr_main.c | * | |||
* +---------+ +-------------+ +-------------+ +--------------+ * | |||
* * | |||
************************************************************************************************ | |||
``` | |||
The `lora.py` component is the front end/UI that is used to send commands | |||
to controller. This program establishes a secure communications channel | |||
to the controller. The controller's firmware is in `lora.irr.elf`, and | |||
the main source file is `irr_main.c`. | |||
The middle to components, `loraserv.py` and `lora.gw.elf` are used to | |||
pass messages between the former two. The `loraserv.py` program takes | |||
multicast datagrams that are received on 239.192.76.111:21089, which | |||
are with out any framing, prepends `pkt:`, hex encodes the data and | |||
terminated w/ the new line character, and sends them via the USB VCP | |||
provided by `lora.gw.elf`. The gateway firmware then decodes the | |||
packet and transmits it via the LoRa radio to the irrigation | |||
controller. Any received packet is returned similarly, but this time | |||
with `data:` prepended, for `loraserv.py` to multicast back to | |||
`lora.py`. | |||
The reason no particular framing is required for addressing or | |||
destination is that the protocol is secure, and only the party that | |||
is able to decrypt the proper packets will be accepted, and any invalid | |||
packets will be ignored. | |||
Building | |||
-------- | |||
The build system uses the BSD flavor of make. This is the default | |||
make on the BSDs, originally called pmake, but also available as bsdmake | |||
for MacOSX, and available as [bmake](https://crufty.net/help/sjg/bmake.html). | |||
It also depends upon ARM's [GNU Arm Embedded | |||
Toolchain](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm), | |||
which uses gcc as the compiler. It would be good to get it | |||
cross-compile with clang as well, but that requires finding a libc like | |||
the nano libc that is provided by the toolchain. | |||
One of the required parameters of the build is the shared key used for | |||
authentication. A random key can be made using the command: | |||
`make irrigation_key`, or it can be provided via the make command by | |||
setting the variable IRR_KEY. | |||
Note: Both IRR_KEY and the argument to `lora.py` will encode the | |||
provided key to UTF-8. | |||
Once ARM's toolchain is in your path, the following should work: | |||
``` | |||
export MAKEOBJDIR=build | |||
mkdir $MAKEOBJDIR | |||
bsdmake all IRR_KEY=<sharedkey> | |||
``` | |||
And in the directory `build`, two files, `lora.irr.elf` and | |||
`lora.gw.elf` should be present. The file `lora.irr.elf` should be | |||
flashed on the Node151 device that is used for interfacing to the | |||
irrigation system as described in [Deploying](#deploying). The file | |||
`lora.gw.elf` should be used on another Node151 that will be attached | |||
to a computer used as the gateway which runs the `loraserv.py` software | |||
as described in [Using](#using). | |||
Flashing | |||
-------- | |||
Flashing can be done via the open source tool | |||
[OpenOCD](https://sourceforge.net/projects/openocd/). For this, I use | |||
a Digilent HS1 JTAG programmer utilizing the [resistor | |||
hack](https://github.com/ntfreak/openocd/blob/master/tcl/interface/ftdi/swd-resistor-hack.cfg) | |||
to allow an FTDI JTAG programmer to control the bi-directional `SWIO` | |||
pin. | |||
One caveat w/ MacOSX, is that it may be necessary to unload the kext | |||
`com.apple.driver.AppleUSBFTDI` via the command: | |||
``` | |||
sudo kextunload -b com.apple.driver.AppleUSBFTDI | |||
``` | |||
as OpenOCD wants direct access to the FTDI driver. | |||
Once that happens, the device can be programmed using the following | |||
command: | |||
``` | |||
sudo openocd -f interface/ftdi/digilent-hs1.cfg -f interface/ftdi/swd-resistor-hack.cfg -f target/stm32l1.cfg -c "init" -c "reset init" -c "program build/lora.irr.elf verify reset exit" | |||
``` | |||
Pins | |||
---- | |||
The [pinout guide for the Node151](https://resource.heltec.cn/download/LoRa_Node_151/LoRa_Node_151_Pinout_Diagram.pdf). | |||
The default pins PB5-7,9 are used as active low controls for the relays. | |||
They are mapped to channels 0 through 3 respectively. The LED on PB8 | |||
is mapped to channel 4. This is useful for testing if a command works | |||
or not. | |||
The pin PB15 is used as an analog input for an RNG source. This pin | |||
should be grounded. | |||
Deploying | |||
--------- | |||
Here is a diagram of the connections: | |||
``` | |||
******************************************************************************************* | |||
* * | |||
* GND * | |||
* +--------------------------------------------------+ * | |||
* | | * | |||
* +--------+ ~/~ +-+-----------+ GND +---------+ GPIO +-+--------------+ * | |||
* | 24V AC +--------+ +----------------+ Node151 +---------+ Relay | * | |||
* +--------+ | | +-+-------+ +-+--------------+ * | |||
* | | +5V -> VUSB | | * | |||
* | AC-DC PS 5V +------------------+ | +5V -> JD-VCC * | |||
* | | | * | |||
* | | | * | |||
* | +--------------------------------------+ * | |||
* +-------------+ * | |||
* * | |||
******************************************************************************************* | |||
``` | |||
The normal supply used for irrigation values is 24V AC. This means | |||
an additional power supply is needed to convert to the 5V supply that | |||
is used by the Node151. Make sure this is well filtered as both the | |||
relays on the board (talked about below), and the irrigation valves | |||
will cause significant noise. The first PS I made was a simple DC-DC | |||
buck converter + a full wave rectifier which, while alone was enough | |||
to power the uC, was not enough when the relays were actuated, and even | |||
when a little bit of filtering was added after the rectifier (22uF), | |||
enough to keep it happy w/ the relays, it was not enough when the | |||
irrigation valves actuated. | |||
In order to control the values, a relay board, similar to [this | |||
one](https://www.amazon.com/ELEGOO-Channel-Optocoupler-Arduino-Raspberry/dp/B01HEQF5HU), | |||
can be used. Despite the GPIO on the Node151 being 3.3V, and the | |||
relays requiring 5V, the jumper on the right side, VCC-JD-VCC, can be | |||
removed to allow dual voltage operation. The GND on the input/VCC | |||
pinout actually belongs to the relay power via JD-VCC, and NOT for the | |||
VCC->INx pins, despite them being next to each other. The GND and | |||
JD-VCC should be connected to the 5V power supply, while VCC is | |||
connected to VDD on the Node151, and INx pins to the respective | |||
GPIO pins. | |||
Using | |||
----- | |||
The `lora.py` script requires at least Python 3.8. It also uses the | |||
strobe library that in distributed in this repo. In general a | |||
[virtualenv](https://virtualenv.pypa.io/en/latest/) is recommended for | |||
all installed Python software to prevent version conflicts, but is not | |||
always necessary. The `requirements.txt` file contains the necessary | |||
modules to be installed, but simply adding the directory | |||
`strobe/python` to PYTHONPATH should be sufficient. | |||
The program `loraserv.py` takes a single argument, which is the device | |||
file for the VCP that runs on the gateway. In my case, the device | |||
name is `/dev/cu.usbmodem1451` as I am on my MacBook Pro, so the command | |||
to launch the gateway is simply: | |||
``` | |||
python3 loraserv.py /dev/cu.usbmodem1451 | |||
``` | |||
Note: On FreeBSD, the default open mode echos characters back to the | |||
gateway causing it not to work. It is advised to setup the modem tty | |||
via the command: | |||
``` | |||
stty -f /dev/cuaU0.init gfmt1:cflag=cb00:iflag=2e02:lflag=43:oflag=2:discard=f:dsusp=19:eof=4:eol=ff:eol2=ff:erase=7f:erase2=8:intr=3:kill=15:lnext=16:min=1:quit=1c:reprint=12:start=11:status=14:stop=13:susp=1a:time=0:werase=17:ispeed=9600:ospeed=9600 | |||
``` | |||
before running the `loraserv.py` command. Replace `/dev/cuaU0.init` | |||
with the respective device. The above was generated by running | |||
`cu -l /dev/cuaU0` in one terminal, while obtaining the info via | |||
`stty -g -f /dev/cuaU0` in another terminal. | |||
Once that is running, then the `lora.py` program's multicast packets | |||
will be forwarded out via the LoRa radio. | |||
To test it, a simple `ping` command can be used, or turning on or off | |||
the on board LED via channel 4 using the `setunset` command. The ping | |||
command: | |||
``` | |||
python3 lora.py -s <sharedkey> ping | |||
``` | |||
To turn off the LED (which defaults to on): | |||
``` | |||
python3 lora.py -s <sharedkey> setunset 4 0 | |||
``` | |||
Either of these commands should exit w/o message or error. | |||
Multiple commands may be specified by separating them w/ `--` (two | |||
hyphens). For example: | |||
``` | |||
python3 lora.py -s <sharedkey> -- setunset 4 0 -- setunset 1 1 | |||
``` | |||
The first `--` is required to denote the end of option parsing, | |||
otherwise the second `--` will be used, and the first `setunset` | |||
command will be tried to be parsed as an argument. | |||
If you have regular set of commands to run, they can be stored in a | |||
file. Each line will be a single command, so you can have a file | |||
similar to: | |||
``` | |||
waitfor 5000 | |||
setunset 0 0 | |||
setunset 1 0 | |||
setunset 2 0 | |||
setunset 3 0 | |||
runfor 60000 0 | |||
waitfor 2000 | |||
runfor 60000 1 | |||
waitfor 2000 | |||
runfor 60000 2 | |||
waitfor 2000 | |||
runfor 60000 3 | |||
``` | |||
which will make sure all the valves are turned off, then run each one | |||
in succession for 60 seconds, with a 2 second wait between. | |||
There are two types of commands, ones that execute immediately, and ones | |||
that are queued up for future execution. The immediate commands are: | |||
* `adv`: Sets the current executing command to 0. An optional argument | |||
specifies how many commands to advance by. Note that only the time | |||
they are run is set to zero, so channels will be very briefly | |||
activated. See the clear command to avoid this. | |||
* `clear`: No argument, removes any future commands. Current command | |||
remains executing. To clear all commands and stop all operations, | |||
first do a `clear`, followed by an `adv`. | |||
* `ping`: No argument, used to verify communication works. | |||
* `setunset`: First argument is channel, second argument is 0 or 1, | |||
specifying to turn the channel off (0) or on (1). | |||
The following commands are queued. The first argument is the number | |||
of milliseconds to run the command for before advancing to the next | |||
command. The available commands are: | |||
* `runfor`: And additional argument specifies the channel. The | |||
channel will be set to on, and then when the command completes, The | |||
channel will be set to off. | |||
* `waitfor`: Wait for the specified time before advancing to the next | |||
enqueued command. | |||
Notes | |||
----- | |||
Significant portions of this code is copied from various reference | |||
implementations. Basic review shows that it is of questionable quality. | |||
It would be good to fully review all the code under stm32 and loramac | |||
for any bugs and other issues. The buffer handling has already been | |||
improved, but there is still plety of work that can be done to improve | |||
it further. | |||
<!-- Markdeep: --><style class="fallback">body{visibility:hidden;white-space:pre;font-family:monospace}</style><script src="markdeep.min.js" charset="utf-8"></script><script src="https://casual-effects.com/markdeep/latest/markdeep.min.js" charset="utf-8"></script><script>window.alreadyProcessedMarkdeep||(document.body.style.visibility="visible")</script> |
@@ -1,293 +1,19 @@ | |||
LoRa Irrigation System | |||
====================== | |||
Syote: Secure IoT | |||
================= | |||
This project is to build an irrigation system from LoRa capable | |||
microcontrollers. The [Heltec Node151](https://heltec.org/project/lora-node-151/) | |||
was chosen due to it's small size and inexpensive cost. | |||
This project started off as a project to control an [irrigation system | |||
via a LoRa radio](LORA-IRR.md), but the core architecture of the | |||
communication and security can easily be reused for other projects. | |||
Design Decisions | |||
---------------- | |||
The projects that make use of the core protocol are included in this | |||
repo to make development easier for now, but if/when the project gets | |||
large enough, they will be broken out into their own repositories. | |||
While investigating this project, the LoraWAN protocol was investigated, | |||
but after looking at the code complexity and other operational | |||
requirements, if was decided that for this project, it was safer to | |||
target a direct Node to Node style communication system. This would | |||
allow the implementation to be more simple, and security to be built in | |||
(LoRaWAN does have a crypto layer, BUT, trusting/auditing it and any | |||
library that implements it would be a larger task than I want to | |||
undertake). It could also be used for other projects that need | |||
security. | |||
One of the other requirements is that the code be 100% open sourced, | |||
not GPL licensed, and no proprietary components. This meant that using | |||
IDE's like ST's STM32CubeIDE which is only available in binary form | |||
was not a choice, as that would preclude building on an operating | |||
system other than Windows/MacOSX/Linux. | |||
Architecture | |||
------------ | |||
There are a number of components to make this system work. The overall | |||
flow is: | |||
<!-- If using MarkDeep, remove the triple backticks from this and the diagram below --> | |||
``` | |||
************************************************************************************************ | |||
* * | |||
* +---------+ +-------------+ +-------------+ +--------------+ * | |||
* | lora.py | multicast | loraserv.py | USB VCP | lora.gw.elf | LoRa | lora.irr.elf | * | |||
* | +--------------+ +------------+ main.c +---------+ irr_main.c | * | |||
* +---------+ +-------------+ +-------------+ +--------------+ * | |||
* * | |||
************************************************************************************************ | |||
``` | |||
The `lora.py` component is the front end/UI that is used to send commands | |||
to controller. This program establishes a secure communications channel | |||
to the controller. The controller's firmware is in `lora.irr.elf`, and | |||
the main source file is `irr_main.c`. | |||
The middle to components, `loraserv.py` and `lora.gw.elf` are used to | |||
pass messages between the former two. The `loraserv.py` program takes | |||
multicast datagrams that are received on 239.192.76.111:21089, which | |||
are with out any framing, prepends `pkt:`, hex encodes the data and | |||
terminated w/ the new line character, and sends them via the USB VCP | |||
provided by `lora.gw.elf`. The gateway firmware then decodes the | |||
packet and transmits it via the LoRa radio to the irrigation | |||
controller. Any received packet is returned similarly, but this time | |||
with `data:` prepended, for `loraserv.py` to multicast back to | |||
`lora.py`. | |||
The reason no particular framing is required for addressing or | |||
destination is that the protocol is secure, and only the party that | |||
is able to decrypt the proper packets will be accepted, and any invalid | |||
packets will be ignored. | |||
Building | |||
Projects | |||
-------- | |||
The build system uses the BSD flavor of make. This is the default | |||
make on the BSDs, originally called pmake, but also available as bsdmake | |||
for MacOSX, and available as [bmake](https://crufty.net/help/sjg/bmake.html). | |||
It also depends upon ARM's [GNU Arm Embedded | |||
Toolchain](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm), | |||
which uses gcc as the compiler. It would be good to get it | |||
cross-compile with clang as well, but that requires finding a libc like | |||
the nano libc that is provided by the toolchain. | |||
One of the required parameters of the build is the shared key used for | |||
authentication. A random key can be made using the command: | |||
`make irrigation_key`, or it can be provided via the make command by | |||
setting the variable IRR_KEY. | |||
Note: Both IRR_KEY and the argument to `lora.py` will encode the | |||
provided key to UTF-8. | |||
Once ARM's toolchain is in your path, the following should work: | |||
``` | |||
export MAKEOBJDIR=build | |||
mkdir $MAKEOBJDIR | |||
bsdmake all IRR_KEY=<sharedkey> | |||
``` | |||
And in the directory `build`, two files, `lora.irr.elf` and | |||
`lora.gw.elf` should be present. The file `lora.irr.elf` should be | |||
flashed on the Node151 device that is used for interfacing to the | |||
irrigation system as described in [Deploying](#deploying). The file | |||
`lora.gw.elf` should be used on another Node151 that will be attached | |||
to a computer used as the gateway which runs the `loraserv.py` software | |||
as described in [Using](#using). | |||
Flashing | |||
-------- | |||
Flashing can be done via the open source tool | |||
[OpenOCD](https://sourceforge.net/projects/openocd/). For this, I use | |||
a Digilent HS1 JTAG programmer utilizing the [resistor | |||
hack](https://github.com/ntfreak/openocd/blob/master/tcl/interface/ftdi/swd-resistor-hack.cfg) | |||
to allow an FTDI JTAG programmer to control the bi-directional `SWIO` | |||
pin. | |||
One caveat w/ MacOSX, is that it may be necessary to unload the kext | |||
`com.apple.driver.AppleUSBFTDI` via the command: | |||
``` | |||
sudo kextunload -b com.apple.driver.AppleUSBFTDI | |||
``` | |||
as OpenOCD wants direct access to the FTDI driver. | |||
Once that happens, the device can be programmed using the following | |||
command: | |||
``` | |||
sudo openocd -f interface/ftdi/digilent-hs1.cfg -f interface/ftdi/swd-resistor-hack.cfg -f target/stm32l1.cfg -c "init" -c "reset init" -c "program build/lora.irr.elf verify reset exit" | |||
``` | |||
Pins | |||
---- | |||
The [pinout guide for the Node151](https://resource.heltec.cn/download/LoRa_Node_151/LoRa_Node_151_Pinout_Diagram.pdf). | |||
The default pins PB5-7,9 are used as active low controls for the relays. | |||
They are mapped to channels 0 through 3 respectively. The LED on PB8 | |||
is mapped to channel 4. This is useful for testing if a command works | |||
or not. | |||
The pin PB15 is used as an analog input for an RNG source. This pin | |||
should be grounded. | |||
Deploying | |||
--------- | |||
Here is a diagram of the connections: | |||
``` | |||
******************************************************************************************* | |||
* * | |||
* GND * | |||
* +--------------------------------------------------+ * | |||
* | | * | |||
* +--------+ ~/~ +-+-----------+ GND +---------+ GPIO +-+--------------+ * | |||
* | 24V AC +--------+ +----------------+ Node151 +---------+ Relay | * | |||
* +--------+ | | +-+-------+ +-+--------------+ * | |||
* | | +5V -> VUSB | | * | |||
* | AC-DC PS 5V +------------------+ | +5V -> JD-VCC * | |||
* | | | * | |||
* | | | * | |||
* | +--------------------------------------+ * | |||
* +-------------+ * | |||
* * | |||
******************************************************************************************* | |||
``` | |||
The normal supply used for irrigation values is 24V AC. This means | |||
an additional power supply is needed to convert to the 5V supply that | |||
is used by the Node151. Make sure this is well filtered as both the | |||
relays on the board (talked about below), and the irrigation valves | |||
will cause significant noise. The first PS I made was a simple DC-DC | |||
buck converter + a full wave rectifier which, while alone was enough | |||
to power the uC, was not enough when the relays were actuated, and even | |||
when a little bit of filtering was added after the rectifier (22uF), | |||
enough to keep it happy w/ the relays, it was not enough when the | |||
irrigation valves actuated. | |||
In order to control the values, a relay board, similar to [this | |||
one](https://www.amazon.com/ELEGOO-Channel-Optocoupler-Arduino-Raspberry/dp/B01HEQF5HU), | |||
can be used. Despite the GPIO on the Node151 being 3.3V, and the | |||
relays requiring 5V, the jumper on the right side, VCC-JD-VCC, can be | |||
removed to allow dual voltage operation. The GND on the input/VCC | |||
pinout actually belongs to the relay power via JD-VCC, and NOT for the | |||
VCC->INx pins, despite them being next to each other. The GND and | |||
JD-VCC should be connected to the 5V power supply, while VCC is | |||
connected to VDD on the Node151, and INx pins to the respective | |||
GPIO pins. | |||
Using | |||
----- | |||
The `lora.py` script requires at least Python 3.8. It also uses the | |||
strobe library that in distributed in this repo. In general a | |||
[virtualenv](https://virtualenv.pypa.io/en/latest/) is recommended for | |||
all installed Python software to prevent version conflicts, but is not | |||
always necessary. The `requirements.txt` file contains the necessary | |||
modules to be installed, but simply adding the directory | |||
`strobe/python` to PYTHONPATH should be sufficient. | |||
The program `loraserv.py` takes a single argument, which is the device | |||
file for the VCP that runs on the gateway. In my case, the device | |||
name is `/dev/cu.usbmodem1451` as I am on my MacBook Pro, so the command | |||
to launch the gateway is simply: | |||
``` | |||
python3 loraserv.py /dev/cu.usbmodem1451 | |||
``` | |||
Note: On FreeBSD, the default open mode echos characters back to the | |||
gateway causing it not to work. It is advised to setup the modem tty | |||
via the command: | |||
``` | |||
stty -f /dev/cuaU0.init gfmt1:cflag=cb00:iflag=2e02:lflag=43:oflag=2:discard=f:dsusp=19:eof=4:eol=ff:eol2=ff:erase=7f:erase2=8:intr=3:kill=15:lnext=16:min=1:quit=1c:reprint=12:start=11:status=14:stop=13:susp=1a:time=0:werase=17:ispeed=9600:ospeed=9600 | |||
``` | |||
before running the `loraserv.py` command. Replace `/dev/cuaU0.init` | |||
with the respective device. The above was generated by running | |||
`cu -l /dev/cuaU0` in one terminal, while obtaining the info via | |||
`stty -g -f /dev/cuaU0` in another terminal. | |||
Once that is running, then the `lora.py` program's multicast packets | |||
will be forwarded out via the LoRa radio. | |||
To test it, a simple `ping` command can be used, or turning on or off | |||
the on board LED via channel 4 using the `setunset` command. The ping | |||
command: | |||
``` | |||
python3 lora.py -s <sharedkey> ping | |||
``` | |||
To turn off the LED (which defaults to on): | |||
``` | |||
python3 lora.py -s <sharedkey> setunset 4 0 | |||
``` | |||
Either of these commands should exit w/o message or error. | |||
Multiple commands may be specified by separating them w/ `--` (two | |||
hyphens). For example: | |||
``` | |||
python3 lora.py -s <sharedkey> -- setunset 4 0 -- setunset 1 1 | |||
``` | |||
The first `--` is required to denote the end of option parsing, | |||
otherwise the second `--` will be used, and the first `setunset` | |||
command will be tried to be parsed as an argument. | |||
If you have regular set of commands to run, they can be stored in a | |||
file. Each line will be a single command, so you can have a file | |||
similar to: | |||
``` | |||
waitfor 5000 | |||
setunset 0 0 | |||
setunset 1 0 | |||
setunset 2 0 | |||
setunset 3 0 | |||
runfor 60000 0 | |||
waitfor 2000 | |||
runfor 60000 1 | |||
waitfor 2000 | |||
runfor 60000 2 | |||
waitfor 2000 | |||
runfor 60000 3 | |||
``` | |||
which will make sure all the valves are turned off, then run each one | |||
in succession for 60 seconds, with a 2 second wait between. | |||
There are two types of commands, ones that execute immediately, and ones | |||
that are queued up for future execution. The immediate commands are: | |||
* `adv`: Sets the current executing command to 0. An optional argument | |||
specifies how many commands to advance by. Note that only the time | |||
they are run is set to zero, so channels will be very briefly | |||
activated. See the clear command to avoid this. | |||
* `clear`: No argument, removes any future commands. Current command | |||
remains executing. To clear all commands and stop all operations, | |||
first do a `clear`, followed by an `adv`. | |||
* `ping`: No argument, used to verify communication works. | |||
* `setunset`: First argument is channel, second argument is 0 or 1, | |||
specifying to turn the channel off (0) or on (1). | |||
The following commands are queued. The first argument is the number | |||
of milliseconds to run the command for before advancing to the next | |||
command. The available commands are: | |||
* `runfor`: And additional argument specifies the channel. The | |||
channel will be set to on, and then when the command completes, The | |||
channel will be set to off. | |||
* `waitfor`: Wait for the specified time before advancing to the next | |||
enqueued command. | |||
Notes | |||
----- | |||
[LoRa Irrigation](LORA-IRR.md): Control over LoRa radio. | |||
Significant portions of this code is copied from various reference | |||
implementations. Basic review shows that it is of questionable quality. | |||
It would be good to fully review all the code under stm32 and loramac | |||
for any bugs and other issues. The buffer handling has already been | |||
improved, but there is still plety of work that can be done to improve | |||
it further. | |||
[RS-485 USB HID KVM](RS485HID.md): USB Keyboard over RS-485 | |||
<!-- Markdeep: --><style class="fallback">body{visibility:hidden;white-space:pre;font-family:monospace}</style><script src="markdeep.min.js" charset="utf-8"></script><script src="https://casual-effects.com/markdeep/latest/markdeep.min.js" charset="utf-8"></script><script>window.alreadyProcessedMarkdeep||(document.body.style.visibility="visible")</script> |
@@ -0,0 +1,54 @@ | |||
USB Keyboard over RS-485 | |||
======================== | |||
The project is to have a device that appears to a computer as a USB | |||
keyboard, but it receives it's key presses from another computer via an | |||
RS-485 multidrop bus. It will use the Syote library for communications, | |||
and as there can be multiple devices on the bus, a single gateway | |||
controller can service multiple such keyboards, making it a nice option | |||
for an IPMI like solution. It is also expected that GPIOs of the device | |||
can be used to control the power switches, along with observing various | |||
LEDs. As most microcontrollers have an ADC, it could theoretically | |||
support beeps from the PC speaker. | |||
Devices | |||
------- | |||
These are the device that are under conideration for the project: | |||
### STM32F103C8 | |||
64KB flash | |||
Currently looking at USART3, B0 for DE, B1 for RE. | |||
Table 5 pin definitions of stm32f103c8.pdf | |||
(all can be remapped) | |||
USART has idle line detction | |||
USART1_TX PA9 5v tollerant | |||
USART1_RX PA10 5v tollerant | |||
USART2_TX PA2 NOT 5v tollerant | |||
USART2_RX PA3 NOT 5v tollerant | |||
USART3_TX PB10 5v tollerant | |||
USART3_RX PB11 5v tollerant | |||
flash: 0/x | |||
boot loader (an2606) pattern 1: 1/0 | |||
embedded sram: 1/1 | |||
top jumper BOOT0/44 | |||
bottom jumper BOOT1/PB2/20 | |||
### MAX485 | |||
This requires a 5V VCC. There is a 3.3V part called the MAX3485, but | |||
as often micros can be 5V tollerant, and the MAX485 is fine w/ logic | |||
levels down to 2V, this should be fine. | |||
D - Driver | |||
DE Driver enable (high enable) | |||
DI Driver input | |||
R - Receiver | |||
RO Receiver output | |||
/RE Receiver enable (low enable) |