@@ -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> | <!-- 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) |