Compare commits
84 Commits
Author | SHA1 | Date | |
---|---|---|---|
15af0c7e9a | |||
2bb280c208 | |||
![]() |
6218a4a4c7 | ||
![]() |
370b284bb6 | ||
![]() |
8da220cbdb | ||
![]() |
97aacae7b9 | ||
![]() |
052c350dad | ||
![]() |
d11fda9a71 | ||
![]() |
51b7789311 | ||
![]() |
458dfd2621 | ||
![]() |
30578560cc | ||
![]() |
96f890588d | ||
![]() |
7594f5396e | ||
![]() |
789c5f230f | ||
![]() |
e5b5a36a06 | ||
![]() |
8a2ef9be32 | ||
![]() |
cc60e10a33 | ||
![]() |
c8da085c22 | ||
![]() |
6422fa3a8a | ||
![]() |
d815054215 | ||
![]() |
4de79a9d6c | ||
![]() |
f00cb821e3 | ||
![]() |
f508e869ed | ||
![]() |
485fa38021 | ||
![]() |
0689ea7e9e | ||
![]() |
17062e17cc | ||
![]() |
c1e12c7286 | ||
![]() |
4be02dca3f | ||
![]() |
7a265978f1 | ||
![]() |
15da3e7dc8 | ||
![]() |
17aa9f611e | ||
![]() |
f5e0bcc72b | ||
![]() |
a19d1dfe54 | ||
![]() |
4feb32a702 | ||
![]() |
76f390897f | ||
![]() |
b5c6b0741d | ||
![]() |
69865a06e6 | ||
![]() |
0e67219478 | ||
![]() |
5c78d839ef | ||
![]() |
6eb004d420 | ||
![]() |
b1316d8d9d | ||
![]() |
2ebf823f32 | ||
![]() |
160219215e | ||
![]() |
1094ada372 | ||
![]() |
f4968c0b66 | ||
![]() |
0c1d20ce5c | ||
![]() |
dbfc10a358 | ||
![]() |
fbd399f310 | ||
![]() |
5606de2e30 | ||
![]() |
38af1654af | ||
![]() |
c651235a54 | ||
![]() |
c07685d07a | ||
![]() |
b17f299211 | ||
![]() |
4f355add20 | ||
![]() |
01d921ff10 | ||
![]() |
f4f173d22d | ||
![]() |
09d9733046 | ||
![]() |
d316f6c884 | ||
![]() |
a11d33d0d3 | ||
![]() |
80242b3031 | ||
![]() |
7f1b6089db | ||
![]() |
ec2b571047 | ||
![]() |
7466d161ef | ||
![]() |
1e036907a9 | ||
![]() |
096e6a47ac | ||
![]() |
b50ab170ce | ||
![]() |
92eea55eaa | ||
![]() |
1481348f3d | ||
![]() |
f63c52ebf5 | ||
![]() |
22ada2c9e0 | ||
![]() |
d74bacde6b | ||
![]() |
5c1021abfd | ||
![]() |
03c484f1c6 | ||
![]() |
f4704f57ce | ||
![]() |
55b1e7559a | ||
![]() |
5368b67f95 | ||
![]() |
58794502cf | ||
![]() |
57899c5600 | ||
![]() |
0496e468aa | ||
![]() |
8443725f70 | ||
![]() |
e3b308aad7 | ||
![]() |
659ae261b1 | ||
![]() |
b8a657de73 | ||
![]() |
71bce7ad0f |
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
*.hex
|
||||||
|
*.elf
|
||||||
|
.DS_Store
|
||||||
|
|
BIN
Gerber_Stir V2.zip
Normal file
183
README.md
@ -1,23 +1,62 @@
|
|||||||
# Dual magnetic stir controller
|
# Dual magnetic stir controller V2
|
||||||
|
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
This is the Arduino sketch to build a double magnetic stirrer based on 2 fans, a 1602 LCD display, a KY-040 encoder and an Arduino (e.g. Uno, Leonardo, Pro Micro).
|
This is the Arduino project to build a double magnetic stirrer based on 2 fans, a 1602 LCD display, a KY-040 encoder and an Arduino Nano and a special PCB designed in the Hobbybrauer-Forum.
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="https://github.com/micworg/stir/blob/master/images/stir.jpg" width=500>
|
<img src="https://git.fhi.mpg.de/mike/stir/raw/branch/master/images/stir+pcb.jpg" width=700>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
V2 supports dual voltage for the fans which increases the speed range.
|
||||||
|
|
||||||
|
In order to put the stirrer into operation you have to change the settings in stir.ino according to your setup (see below).
|
||||||
|
|
||||||
|
The stir V2 software is compatible with V1 hardware if you have used neither the RS232 Api nor the OFF0 and OFF1 relais pins.
|
||||||
|
|
||||||
|
|
||||||
|
## Part List
|
||||||
|
|
||||||
|
* 1x PCB "Stir V2.0"
|
||||||
|
* 1x Arduino Nano V3
|
||||||
|
* 1x [Voltage regulator TE818 5-24V to 5V 3A step down buck converter](https://www.ebay.de/itm/5x-Voltage-Regulator-5-24V-to-5V-3A-Step-Down-Buck-Converter-Power-Module-TE818/133109140535?ssPageName=STRK%3AMEBIDX%3AIT&_trksid=p2057872.m2749.l2649)
|
||||||
|
* 2x [Relais Omron G5Q-1-EU 5DC switching printrelais 5 V/DC 5A](https://www.conrad.de/de/p/omron-g5q-1-eu-5dc-printrelais-5-v-dc-5-a-1-wechsler-1-st-503930.html)
|
||||||
|
* 2x [Diode 1N4148 Diotec](https://www.conrad.de/de/p/stmicroelectronics-schottky-diode-gleichrichter-1n5822-do-201ad-40-v-einzeln-168275.html)
|
||||||
|
* 1x [Electrolytic capacitor 1000µF/16V Yageo SE016M1000B5S-1015](https://www.conrad.de/de/p/yageo-se016m1000b5s-1015-elektrolyt-kondensator-radial-bedrahtet-5-mm-1000-f-16-v-20-x-h-10-mm-x-15-mm-1-st-445386.html)
|
||||||
|
* 2x [Diode 1N5822 STMicroelectronics Schottky-Diode](https://www.conrad.de/de/p/diotec-ultraschnelle-si-diode-1n4148-sod-27-75-v-150-ma-162280.html)
|
||||||
|
* 4x [Metal film resistor 10 KOhm 0,6 W](https://www.conrad.de/de/p/rs-pro-metallschichtwiderstand-10k-0-5-0-6w-807200469.html)
|
||||||
|
* 2x Fan BeQuiet SilentWings 3 120mm PWM Highspeed or Noctua NF-R8 Redux-1800 80mm PWM
|
||||||
|
* 1x Power supply 12V-16V DC / 2A
|
||||||
|
* 1x Built-in socket for plug-in power supply unit
|
||||||
|
* 1x I2C 16x2 Arduino LCD Display Module
|
||||||
|
* 1x [Rotary encoder KY-040](https://www.conrad.de/de/p/joy-it-kodierter-drehschalter-rotary-encoder-1695709.html)
|
||||||
|
* 2x Magnet mount (3D printed)
|
||||||
|
* 4x Neodymium magnet 20x10 mm (N52, 1 oder 2 mm dick)
|
||||||
|
|
||||||
|
In addition, a housing is required that can be individually designed according to possibilities and capabilities.
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img src="https://git.fhi.mpg.de/mike/stir/raw/branch/master/images/v2_board.jpg" width=350>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
In order to put the stirrer into operation you have to change the settings in stir.ino according to your setup.
|
|
||||||
|
|
||||||
## Reference
|
## Reference
|
||||||
|
|
||||||
This project was created based on an idea from the Hobbybrauer-Forum and would not be possible without the ideas from there.
|
This project was created based on an idea from the german Hobbybrauer-Forum and would not be possible without the ideas from there.
|
||||||
|
|
||||||
The forum: https://hobbybrauer.de/
|
The forum: https://hobbybrauer.de/
|
||||||
|
|
||||||
The thread: https://hobbybrauer.de/forum/viewtopic.php?f=21&t=1456
|
The thread: https://hobbybrauer.de/forum/viewtopic.php?f=21&t=1456
|
||||||
|
|
||||||
|
Special thanks for development and testing:
|
||||||
|
|
||||||
|
* Herbert Schmid
|
||||||
|
* Adrian Sigel
|
||||||
|
* Jens Warkentin
|
||||||
|
* Bastian Werner
|
||||||
|
|
||||||
|
|
||||||
## Overview of Functions
|
## Overview of Functions
|
||||||
|
|
||||||
All functions are controlled by the KY-040 encoder:
|
All functions are controlled by the KY-040 encoder:
|
||||||
@ -35,7 +74,13 @@ All functions are controlled by the KY-040 encoder:
|
|||||||
* **OTIME**: turn changes switch off time in hours (the timer activates immediately, 0 = switch off disabled)
|
* **OTIME**: turn changes switch off time in hours (the timer activates immediately, 0 = switch off disabled)
|
||||||
* **RNVAL**: random value range (a random values in this range will be added to speed)
|
* **RNVAL**: random value range (a random values in this range will be added to speed)
|
||||||
* **Other menu options**:
|
* **Other menu options**:
|
||||||
* **BRGHT**: LCD brightness
|
* **CFG**: Configuration menu
|
||||||
|
|
||||||
|
Functions in the congirutation sub menu
|
||||||
|
* **Short Press**: switch between config option and and value.
|
||||||
|
* **Long press**: exit configuration menu.
|
||||||
|
* **Turn**: select configuration option or change value.
|
||||||
|
|
||||||
|
|
||||||
## Display Indicators:
|
## Display Indicators:
|
||||||
|
|
||||||
@ -46,95 +91,39 @@ All functions are controlled by the KY-040 encoder:
|
|||||||
|
|
||||||
## Settings (in stir.ino)
|
## Settings (in stir.ino)
|
||||||
|
|
||||||
|Value|Description|
|
|Value|Config|Description|
|
||||||
|:----|:----------|
|
|:----------------|:-----|:----------|
|
||||||
|`SPEEDINC`|increment of speed values when turning the encoder|
|
|`LGHT` |`LGHT`|LCD display brightness|
|
||||||
|`FANMIN`|fan minimum speed (should be a value at which the fan runs safely) (rpm)|
|
|`SPEEDINC1` |`SPI1`|increment of speed values when turning the encoder (1. range)|
|
||||||
|`FANMAX`|maximum speed of the fan (it is important that this is the real maximum value of the fan) (rpm)|
|
|`SPEEDINC2` |`SPI2`|increment of speed values when turning the encoder (2. range)|
|
||||||
|`BOFF`|if set boost off will also turn the normal mode off|
|
|`SPEEDINC3` |`SPI3`|increment of speed values when turning the encoder (3. range)|
|
||||||
|`BINC`|boost time increment (min)|
|
|`SPEEDSTEP1` |`SPS1`|speed increment steps (increment changes at these values, separates range 1 and 2)|
|
||||||
|`CINC`|catch time increment (min)|
|
|`SPEEDSTEP2` |`SPS2`|speed increment steps (increment changes at these values, separates range 2 and 3))|
|
||||||
|`RINC`|rise time increment (sec)|
|
|`FANMIN` |`FMIN`|fan minimum speed (should be a value at which the fan runs safely) (rpm)|
|
||||||
|`OINC`|off timer increment (hour)|
|
|`FANMAX` |`FMAX`|fan maximum speed (it's important that this is the real maximum value of the fan) (rpm)|
|
||||||
|`CATCHSTOP`|stop interval for stir fish catch function (ms)|
|
|`FANINIT` |`FINI`|set fans to high voltage for 3 sec at boot (0/1)|
|
||||||
|`PWM0`, `PWM1`|PWM output pins for fan speed|
|
|`BOFF` |`BOFF`|if set boost off will also turn the normal mode off (0/1)|
|
||||||
|`PWM2`|PWM output pin for LCD brightness control|
|
|`BINC` |`BINC`|boost time increment (min)|
|
||||||
|`I0`, `I1`|interrupts for rpm measurement (2 and 3 for Leonardo and ProMicro / 0 and 1 for Uno)|
|
|`CINC` |`CINC`|catch time increment (min)|
|
||||||
|`CLK`, `DT`, `SW`|pins for KY-040 encoder|
|
|`RINC` |`RINC`|rise time increment (sec)|
|
||||||
|`OFF0`, `OFF1`|these pins will be set if the fan is off|
|
|`OINC` |`OINC`|off timer increment (hour)|
|
||||||
|`OFFSTATE`|off state (LOW/HIGH)|
|
|`RNDINC` |`RINC`|randon value increment (rpm)|
|
||||||
|`RINTERVAL`|regulation interval (ms)|
|
|`CATCHSTOP` |`CSTP`|stop interval for stir fish catch function (ms)|
|
||||||
|`RDELAY`|extra regulation delay when value changes (ms)|
|
|`PWM0`, `PWM1` | |PWM output pins for fan speed|
|
||||||
|`RTOL`|regulation tolerance (rpm)|
|
|`PWM2` | |PWM output pin for LCD brightness control|
|
||||||
|`RNDINTERVL`|randon value change interval (ms)|
|
|`I0`, `I1` | |interrupts for rpm measurement (0/1 for Uno/Nano, 2/3 for Leonardo/ProMicro)|
|
||||||
|`SINTERVAL`|speed measurement interval (ms)|
|
|`SWAPENC` |`SWEN`|switch KY-040 encoder direxction (0/1)|
|
||||||
|`SAVERAGE`|speed measurement average|
|
|`CLK`, `DT`, `SW`| |pins for KY-040 encoder|
|
||||||
|`SAVETAG`|parameter save identifier|
|
|`R0`, `R0` | |voltage select relais pin|
|
||||||
|`SAVEDELAY`|delay in seconds before parameter will be saved to EEPROM|
|
|`RTHRES` |`RTHR`|voltage switch threshold (rpm)|
|
||||||
|`LCDB`|LCD brightness steps (10 values, 0=off, 255=max)|
|
|`RINTERVAL` |`XINT`|regulation interval (ms)|
|
||||||
|
|`RDELAY` |`XDEL`|extra regulation delay when value changes (ms)|
|
||||||
|
|`RTOL` |`XTOL`|regulation tolerance (rpm)|
|
||||||
|
|`RNDINTERVL` |`RINT`|randon value range change interval (ms)|
|
||||||
|
|`SINTERVAL` |`SINT`|speed measurement interval (ms)|
|
||||||
|
|`SAVERAGE` |`SAVG`|speed measurement average|
|
||||||
|
|`SAVETAG` | |parameter save identifier|
|
||||||
|
|`SAVEDELAY` | |delay in seconds before parameter will be saved to EEPROM|
|
||||||
|
|`LCDB` | |LCD brightness steps (10 values, 0=off, 255=max)|
|
||||||
|
|`RESET` |`RSET`|change this value in configuration menu to 1 for factory reset|
|
||||||
|
|
||||||
## API commands
|
|
||||||
|
|
||||||
Commands are colon separated an can be send via USB/Serial
|
|
||||||
|
|
||||||
|Command|Description|
|
|
||||||
|:------|:----------|
|
|
||||||
|`info`|returns a colon separated string with all parameters (see below)|
|
|
||||||
|`version`|returns the software version|
|
|
||||||
|`on:<0/1>`|switch stirren on|
|
|
||||||
|`off:<0/1>`|switch stirren off|
|
|
||||||
|`bon:<0/1>`|switch boost mode on|
|
|
||||||
|`boff:<0/1>`|switch boost mode off|
|
|
||||||
|`speed:<0/1>:<rpm>`|set stirrer speed (FANMIN-FANMAX rpm)|
|
|
||||||
|`bspeed:<0/1>:<rpm>`|set stirrer boost speed (speed-FANMAX rpm)|
|
|
||||||
|`btime:<0/1>:<min>`|set boost time (0-60)|
|
|
||||||
|`con:<0/1>`|switch catch mode on|
|
|
||||||
|`coff:<0/1>`|switch catch mode off|
|
|
||||||
|`ctime:<0/1>:<min>`|set catch mode interval (60-240 min)|
|
|
||||||
|`rtime:<0/1>:<sec>`|set speed rise time (0-240 sec)|
|
|
||||||
|`rnval:<0/1>:<rpm>`|randon value (0-1000 rpm)|
|
|
||||||
|`otime:<0/1>:<hour>`|switch stirrer off after time in hours (1-99 hour, 0 deactivates switch off)|
|
|
||||||
|
|
||||||
All commands return a colon separated string with all current parameters:
|
|
||||||
|
|
||||||
|Element|Stirrer|Variable in stir.ino|Description|
|
|
||||||
|:------|:------|:-------------------|:----------|
|
|
||||||
| 0|0|`F[0]` |state (0=on, 1=off)|
|
|
||||||
| 1|0|`v[0]` |speed (rpm)|
|
|
||||||
| 2|0|`b[0]` |boost speed (rpm)|
|
|
||||||
| 3|0|`rpm[0]` |rpm|
|
|
||||||
| 4|0|`xpm[0]` |averaged rpm|
|
|
||||||
| 5|0|`r[0]` |regulation value|
|
|
||||||
| 6|0|`bstate[0]`|boost state (0=on, 1=off)|
|
|
||||||
| 7|0|`btime[0]` |boost time (min)|
|
|
||||||
| 8|0|`cat[0]` |fish catch mode state (0=on, 1=off)|
|
|
||||||
| 9|0|`ctime[0]` |fish catch time interval (min)|
|
|
||||||
|10|0|`rtime[0]` |speed rise time (sec)|
|
|
||||||
|11|0|`otime[0]` |switch off time (hour)|
|
|
||||||
|11|0|`rnval[0]` |random value (rpm)|
|
|
||||||
|12|0| |boost remain (sec)|
|
|
||||||
|13|0| |off timer remain (sec)|
|
|
||||||
|14|1|`F[1]` |state (0=on, 1=off)|
|
|
||||||
|15|1|`v[1]` |speed (rpm)|
|
|
||||||
|16|1|`b[1]` |boost speed (rpm)|
|
|
||||||
|17|1|`rpm[1]` |rpm|
|
|
||||||
|18|1|`xpm[1]` |averaged rpm|
|
|
||||||
|19|1|`r[1]` |regulation value|
|
|
||||||
|20|1|`bstate[1]`|boost state (0=on, 1=off)|
|
|
||||||
|21|1|`btime[1]` |boost time (min)|
|
|
||||||
|22|1|`cat[1]` |fish catch mode state (0=on, 1=off)|
|
|
||||||
|23|1|`ctime[1]` |fish catch time interval (min)|
|
|
||||||
|24|1|`rtime[1]` |speed rise time (sec)|
|
|
||||||
|25|1|`otime[1]` |switch off time (hour)|
|
|
||||||
|25|1|`rnval[1]` |random value (rpm)|
|
|
||||||
|26|1| |boost remain (sec)|
|
|
||||||
|27|1| |off timer remain (sec)|
|
|
||||||
|28| | |0=ok, 1=error|
|
|
||||||
|29| | |software version|
|
|
||||||
|
|
||||||
## Schematics
|
|
||||||
|
|
||||||
<p align="center">
|
|
||||||
<img src="https://github.com/micworg/stir/blob/master/images/schematic_leonardo.png" width=500>
|
|
||||||
<img src="https://github.com/micworg/stir/blob/master/images/schematic_uno.png" width=500>
|
|
||||||
</p>
|
|
||||||
|
143
V1 (old)/README.md
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
# Dual magnetic stir controller V1
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
This is the Arduino sketch to build a double magnetic stirrer based on 2 fans, a 1602 LCD display, a KY-040 encoder and an Arduino (e.g. Uno, Nano, Leonardo, Pro Micro).
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img src="https://github.com/micworg/stir/blob/master/images/stir.jpg" width=500>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
In order to put the stirrer into operation you have to change the settings in stir.ino according to your setup.
|
||||||
|
|
||||||
|
## Reference
|
||||||
|
|
||||||
|
This project was created based on an idea from the Hobbybrauer-Forum and would not be possible without the ideas from there.
|
||||||
|
|
||||||
|
The forum: https://hobbybrauer.de/
|
||||||
|
|
||||||
|
The thread: https://hobbybrauer.de/forum/viewtopic.php?f=21&t=1456
|
||||||
|
|
||||||
|
## Overview of Functions
|
||||||
|
|
||||||
|
All functions are controlled by the KY-040 encoder:
|
||||||
|
|
||||||
|
* **Short Press:** change between menu, stirrer 1 and stirrer 2
|
||||||
|
* **Turn when menu is selected**: change between menu items (SPEED, BOOST, BTIME, CATCH, CTIME)
|
||||||
|
* **Long press when menu is selected**: lock all functions (unlock also by long press)
|
||||||
|
* **When a stirrer is selected**:
|
||||||
|
* **SPEED**: turn sets speed, long press switches stirrer on or off.
|
||||||
|
* **BOOST**: turn sets boost speed, long press activates/deactivates the boost function (running time is shown in the display).
|
||||||
|
* **BTIME**: turn changes the boost time in minutes.
|
||||||
|
* **CATCH**: turn activates/deactivates the fishing function
|
||||||
|
* **CTIME**: turn changes the interval in minutes for the fish catching function
|
||||||
|
* **RTIME**: turn changes speed rise time in seconds (applies to power on, stirrer on, boost on and fish catching)
|
||||||
|
* **OTIME**: turn changes switch off time in hours (the timer activates immediately, 0 = switch off disabled)
|
||||||
|
* **RNVAL**: random value range (a random values in this range will be added to speed)
|
||||||
|
* **Other menu options**:
|
||||||
|
* **BRGHT**: LCD brightness
|
||||||
|
|
||||||
|
## Display Indicators:
|
||||||
|
|
||||||
|
* **Bottom Left**: Menu
|
||||||
|
* **Bottom Center/Right**: displays the set values for the stirrers depending on the selected menu item.
|
||||||
|
* **Top Center/Right**: displays the current stirrer speed (or 'OFF' or 'CAT' (Fishing)).
|
||||||
|
* **Top Left**: shows the remaining time of the boost or switch off function.
|
||||||
|
|
||||||
|
## Settings (in stir.ino)
|
||||||
|
|
||||||
|
|Value|Description|
|
||||||
|
|:----|:----------|
|
||||||
|
|`SPEEDINC`|increment of speed values when turning the encoder|
|
||||||
|
|`FANMIN`|fan minimum speed (should be a value at which the fan runs safely) (rpm)|
|
||||||
|
|`FANMAX`|maximum speed of the fan (it is important that this is the real maximum value of the fan) (rpm)|
|
||||||
|
|`BOFF`|if set boost off will also turn the normal mode off|
|
||||||
|
|`BINC`|boost time increment (min)|
|
||||||
|
|`CINC`|catch time increment (min)|
|
||||||
|
|`RINC`|rise time increment (sec)|
|
||||||
|
|`OINC`|off timer increment (hour)|
|
||||||
|
|`CATCHSTOP`|stop interval for stir fish catch function (ms)|
|
||||||
|
|`PWM0`, `PWM1`|PWM output pins for fan speed|
|
||||||
|
|`PWM2`|PWM output pin for LCD brightness control|
|
||||||
|
|`I0`, `I1`|interrupts for rpm measurement (2 and 3 for Leonardo and ProMicro / 0 and 1 for Uno)|
|
||||||
|
|`CLK`, `DT`, `SW`|pins for KY-040 encoder|
|
||||||
|
|`OFF0`, `OFF1`|these pins will be set if the fan is off|
|
||||||
|
|`OFFSTATE`|off state (LOW/HIGH)|
|
||||||
|
|`RINTERVAL`|regulation interval (ms)|
|
||||||
|
|`RDELAY`|extra regulation delay when value changes (ms)|
|
||||||
|
|`RTOL`|regulation tolerance (rpm)|
|
||||||
|
|`RNDINTERVL`|randon value range change interval (ms)|
|
||||||
|
|`SINTERVAL`|speed measurement interval (ms)|
|
||||||
|
|`SAVERAGE`|speed measurement average|
|
||||||
|
|`SAVETAG`|parameter save identifier|
|
||||||
|
|`SAVEDELAY`|delay in seconds before parameter will be saved to EEPROM|
|
||||||
|
|`LCDB`|LCD brightness steps (10 values, 0=off, 255=max)|
|
||||||
|
|
||||||
|
## API commands
|
||||||
|
|
||||||
|
Commands are colon separated an can be send via USB/Serial
|
||||||
|
|
||||||
|
|Command|Description|
|
||||||
|
|:------|:----------|
|
||||||
|
|`info`|returns a colon separated string with all parameters (see below)|
|
||||||
|
|`version`|returns the software version|
|
||||||
|
|`on:<0/1>`|switch stirren on|
|
||||||
|
|`off:<0/1>`|switch stirren off|
|
||||||
|
|`bon:<0/1>`|switch boost mode on|
|
||||||
|
|`boff:<0/1>`|switch boost mode off|
|
||||||
|
|`speed:<0/1>:<rpm>`|set stirrer speed (FANMIN-FANMAX rpm)|
|
||||||
|
|`bspeed:<0/1>:<rpm>`|set stirrer boost speed (speed-FANMAX rpm)|
|
||||||
|
|`btime:<0/1>:<min>`|set boost time (0-60)|
|
||||||
|
|`con:<0/1>`|switch catch mode on|
|
||||||
|
|`coff:<0/1>`|switch catch mode off|
|
||||||
|
|`ctime:<0/1>:<min>`|set catch mode interval (60-240 min)|
|
||||||
|
|`rtime:<0/1>:<sec>`|set speed rise time (0-240 sec)|
|
||||||
|
|`rnval:<0/1>:<rpm>`|set randon value range (0-1000 rpm)|
|
||||||
|
|`otime:<0/1>:<hour>`|switch stirrer off after time in hours (1-99 hour, 0 deactivates switch off)|
|
||||||
|
|
||||||
|
All commands return a colon separated string with all current parameters:
|
||||||
|
|
||||||
|
|Element|Stirrer|Variable in stir.ino|Description|
|
||||||
|
|:------|:------|:-------------------|:----------|
|
||||||
|
| 0|0|`F[0]` |state (0=on, 1=off)|
|
||||||
|
| 1|0|`v[0]` |speed (rpm)|
|
||||||
|
| 2|0|`b[0]` |boost speed (rpm)|
|
||||||
|
| 3|0|`rpm[0]` |rpm|
|
||||||
|
| 4|0|`xpm[0]` |averaged rpm|
|
||||||
|
| 5|0|`r[0]` |regulation value|
|
||||||
|
| 6|0|`bstate[0]`|boost state (0=on, 1=off)|
|
||||||
|
| 7|0|`btime[0]` |boost time (min)|
|
||||||
|
| 8|0|`cat[0]` |fish catch mode state (0=on, 1=off)|
|
||||||
|
| 9|0|`ctime[0]` |fish catch time interval (min)|
|
||||||
|
|10|0|`rtime[0]` |speed rise time (sec)|
|
||||||
|
|11|0|`otime[0]` |switch off time (hour)|
|
||||||
|
|12|0|`rnval[0]` |random value range (rpm)|
|
||||||
|
|13|0|`rnd[0]` |current random value (rpm)|
|
||||||
|
|14|0| |boost remain (sec)|
|
||||||
|
|15|0| |off timer remain (sec)|
|
||||||
|
|16|1|`F[1]` |state (0=on, 1=off)|
|
||||||
|
|17|1|`v[1]` |speed (rpm)|
|
||||||
|
|18|1|`b[1]` |boost speed (rpm)|
|
||||||
|
|19|1|`rpm[1]` |rpm|
|
||||||
|
|20|1|`xpm[1]` |averaged rpm|
|
||||||
|
|21|1|`r[1]` |regulation value|
|
||||||
|
|22|1|`bstate[1]`|boost state (0=on, 1=off)|
|
||||||
|
|23|1|`btime[1]` |boost time (min)|
|
||||||
|
|24|1|`cat[1]` |fish catch mode state (0=on, 1=off)|
|
||||||
|
|25|1|`ctime[1]` |fish catch time interval (min)|
|
||||||
|
|26|1|`rtime[1]` |speed rise time (sec)|
|
||||||
|
|27|1|`otime[1]` |switch off time (hour)|
|
||||||
|
|28|1|`rnval[1]` |random value range (rpm)|
|
||||||
|
|29|1|`rnd[1]` |current random value (rpm)|
|
||||||
|
|30|1| |boost remain (sec)|
|
||||||
|
|31|1| |off timer remain (sec)|
|
||||||
|
|32| | |software version|
|
||||||
|
|33| | |uptime (ms)|
|
||||||
|
|34| | |0=ok, 1=error|
|
||||||
|
|
||||||
|
## Schematics
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img src="https://github.com/micworg/stir/blob/master/images/schematic_leonardo.png" width=500>
|
||||||
|
<img src="https://github.com/micworg/stir/blob/master/images/schematic_uno.png" width=500>
|
||||||
|
</p>
|
BIN
V1 (old)/shields/nano/Gerber_Stir.Nano+StepDown.V3_.zip
Normal file
BIN
V1 (old)/shields/nano/Gerber_Stir_Arduino_Nano.zip
Normal file
15
V1 (old)/shields/nano/README.md
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# Stir Shield
|
||||||
|
|
||||||
|
Stir shields for Arduino NANO from Jens Warkentin.
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<B>Gerber_Stir.Nano+StepDown.V3_.zip<B><BR>
|
||||||
|
<img src="https://github.com/micworg/stir/blob/master/shields/nano/images/topv3.png" width=300>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<B>Gerber_Stir_Arduino_Nano.zip<B><BR>
|
||||||
|
<img src="https://github.com/micworg/stir/blob/master/shields/nano/images/top.png" width=300>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
BIN
V1 (old)/shields/nano/images/top.png
Normal file
After Width: | Height: | Size: 343 KiB |
BIN
V1 (old)/shields/nano/images/topv3.png
Normal file
After Width: | Height: | Size: 228 KiB |
13
V1 (old)/shields/uno/README.md
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# Stir Shield
|
||||||
|
|
||||||
|
Stir shield for Arduino UNO from Adrian Sigel.
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img src="https://github.com/micworg/stir/blob/master/shields/uno/images/pcb_top.png" width=500>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img src="https://github.com/micworg/stir/blob/master/shields/uno/images/pcb_bottom.png" width=500>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
BIN
V1 (old)/shields/uno/files/gerber_file/V1.1 Stir Shield.zip
Normal file
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 51 KiB |
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 64 KiB |
441
V1 (old)/stir.ino
Normal file
@ -0,0 +1,441 @@
|
|||||||
|
/////////////////////////////////////////////////////////////////////////////////////// Stir Control (mwx'2019)
|
||||||
|
#include <EEPROM.h>
|
||||||
|
#include <LiquidCrystal_I2C.h>
|
||||||
|
|
||||||
|
#define MS (long)millis()
|
||||||
|
|
||||||
|
#define SX Serial.print
|
||||||
|
#define SXN Serial.println
|
||||||
|
|
||||||
|
String VERSION = "1.7.3";
|
||||||
|
|
||||||
|
int SPEEDINC = 50; // speed increment (rpm)
|
||||||
|
|
||||||
|
int FANMIN = 200; // fan minimum speed (should be a value at which the fan runs safely) (rpm)
|
||||||
|
int FANMAX = 1600; // fan maximum speed (should be the real maximum value of the fan) (rpm)
|
||||||
|
|
||||||
|
int BOFF = 0; // if set boost off will also turn the normal mode off
|
||||||
|
|
||||||
|
int BINC = 1; // BTIME increment (min)
|
||||||
|
int CINC = 10; // CTIME increment (min)
|
||||||
|
int RINC = 10; // RTIME increment (sec)
|
||||||
|
int OINC = 3; // OTIME increment (hour)
|
||||||
|
|
||||||
|
long CATCHSTOP = 20000; // fish catch stop period (ms)
|
||||||
|
|
||||||
|
int PWM0 = 9; // PWM pin for 1. fan
|
||||||
|
int PWM1 = 10; // PWM pin for 2. fan
|
||||||
|
int PWM2 = 11; // PWM pin for LCD brightness
|
||||||
|
|
||||||
|
int I0 = 2; // interrupt for fan 0 rpm signal (use 2 for Leonardo/ProMicro and 0 for Uno)
|
||||||
|
int I1 = 3; // interrupt for fan 1 rpm signal (use 3 for Leonardo/ProMicro and 1 for Uno)
|
||||||
|
|
||||||
|
int CLK = 5; // clk on KY-040 encoder
|
||||||
|
int DT = 6; // dt on KY-040 encoder
|
||||||
|
int SW = 4; // sw on KY-040 encoder
|
||||||
|
|
||||||
|
int OFF0 = 7; // off state pin 1. fan
|
||||||
|
int OFF1 = 8; // off state pin 2. fan
|
||||||
|
int OFFSTATE = LOW; // off state (LOW/HIGH)
|
||||||
|
|
||||||
|
long RINTERVAL = 5000; // regulation internval (ms)
|
||||||
|
long RDELAY = 3000; // regulation delay on changes (ms)
|
||||||
|
int RTOL = 8; // regulation tolerance (rpm)
|
||||||
|
|
||||||
|
long RNDINTERVAL = 300000; // randon value range change interval (ms)
|
||||||
|
|
||||||
|
long SINTERVAL = 2000; // speed measurement internval (ms)
|
||||||
|
int SAVERAGE = 4; // speed measurement average
|
||||||
|
|
||||||
|
int SAVETAG = 1014; // save tag
|
||||||
|
long SAVEDELAY = 10000; // EEPROM save delay (ms)
|
||||||
|
|
||||||
|
byte LCDB[] = {4,8,16,24,32,64,96,128,192,255}; // LCD brightness steps (10 values, 0=off, 255=max)
|
||||||
|
|
||||||
|
byte aright[] = {0x00,0x08,0x0C,0x0E,0x0C,0x08,0x00,0x00}; // LCD character
|
||||||
|
byte aup[] = {0x04,0x0E,0x1F,0x00,0x00,0x00,0x00,0x00};
|
||||||
|
byte arnd[] = {0x0E,0x0E,0x0E,0x00,0x00,0x00,0x00,0x00};
|
||||||
|
|
||||||
|
LiquidCrystal_I2C lcd(0x27,16,2); // LCD display (connect to SDA/SCL)
|
||||||
|
|
||||||
|
int v[2],b[2],r[2]={0};double q,rpm[2]={0},xpm[2]={0},xb[2]={0},xv[2]={0},rtime[2]; // speed and regulation
|
||||||
|
long ac[2]={0},bc[2]={0}; // interrupt rpm counter
|
||||||
|
long xts,sts,rts,swts,buts,savets,catts[2],stop[2],bts[2],vts[2],ots[2],rndts[2]; // timing
|
||||||
|
int bdelay,bprocess=0,enclast,encval,M=2,S=0; // button/encoder processing
|
||||||
|
int F[2],bstate[2]={0},btime[2],cat[2],ctime[2],cstate[2]={0},bclr=0,SAVE=0,LOCK=0; // operating states
|
||||||
|
int ostate[2]={0},otime[2]={0}; // off timer
|
||||||
|
int brght; // LCD brightness
|
||||||
|
int rnd[2]={0},rnval[2]={0};long seed; // random speed
|
||||||
|
char form[8],out[20];String cmd[8];int icmd[8]; // string buffer
|
||||||
|
|
||||||
|
|
||||||
|
void setup() { ////////////////////////////////////////////////////////////////////////////////////////// SETUP
|
||||||
|
Serial.begin(9600); // start serial
|
||||||
|
|
||||||
|
lcd.init();lcd.clear();lcd.backlight(); // initialize lcd
|
||||||
|
lcd.createChar(0,aright);lcd.createChar(1,aup);lcd.createChar(2,arnd); // load lcd characters
|
||||||
|
pinMode(PWM0,OUTPUT);pinMode(PWM1,OUTPUT);pinMode(PWM2,OUTPUT); // setup PWM pins
|
||||||
|
pinMode(CLK,INPUT);pinMode(DT,INPUT);pinMode(SW,INPUT); // setup KY-040 pins
|
||||||
|
digitalWrite(CLK,true);digitalWrite(DT,true);digitalWrite(SW,true); // turn ON pullup resistors
|
||||||
|
pinMode(OFF0,OUTPUT);pinMode(OFF1,OUTPUT); // setup off state pins
|
||||||
|
|
||||||
|
attachInterrupt(I0,rpmint0,FALLING); // setup interrupts vor rpm in
|
||||||
|
attachInterrupt(I1,rpmint1,FALLING);
|
||||||
|
|
||||||
|
TCCR1A=0;TCCR1B=0;TCNT1=0; // setup timer for 25 kHz PWM
|
||||||
|
TCCR1A=_BV(COM1A1)|_BV(COM1B1)|_BV(WGM11);TCCR1B=_BV(WGM13)|_BV(CS10);ICR1=320;
|
||||||
|
|
||||||
|
SAVE=0; // load/initialize settings
|
||||||
|
if (eer(0)!=SAVETAG) {
|
||||||
|
for (int i=0;i<2;i++) {;v[i]=300;b[i]=700;btime[i]=30;cat[i]=0;ctime[i]=120;rtime[i]=60;F[i]=0;rnval[i]=0;}
|
||||||
|
brght=5;seed=0;
|
||||||
|
eew(0,SAVETAG);save();
|
||||||
|
} else {
|
||||||
|
for (int i=0;i<2;i++) {
|
||||||
|
v[i]=eer(1+i);b[i]=eer(3+i);btime[i]=eer(5+i);cat[i]=eer(7+i);
|
||||||
|
ctime[i]=eer(9+i);F[i]=eer(11+i);rtime[i]=eer(13+i);rnval[i]=eer(15+i);
|
||||||
|
}
|
||||||
|
seed=eer(100)+1;eew(100,seed);randomSeed(seed);
|
||||||
|
brght=eer(101);
|
||||||
|
}
|
||||||
|
|
||||||
|
lset();
|
||||||
|
|
||||||
|
enclast=digitalRead(CLK); // get encoder state
|
||||||
|
|
||||||
|
for (int i=0;i<2;i++) catts[i]=stop[i]=vts[i]=ots[i]=rndts[i]=MS;xts=sts=rts=swts=buts=savets=MS; // timer
|
||||||
|
updatePWM();updatelcd();updatespeed();updatemarker(); // update all
|
||||||
|
|
||||||
|
slcd(0,0,5,VERSION); // show version
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void loop() { //////////////////////////////////////////////////////////////////////////////////////////// LOOP
|
||||||
|
|
||||||
|
if (Serial.available() > 0) { ////////////////////////////////////////////////////////// serial communication
|
||||||
|
int n=cutcmd(Serial.readString());
|
||||||
|
int err=1;
|
||||||
|
int i=cut(icmd[1],0,1);
|
||||||
|
if (cmd[0]=="info" && n==1) {;err=0;}
|
||||||
|
if (cmd[0]=="version" && n==1) {;SXN(VERSION);return;}
|
||||||
|
if (cmd[0]=="save" && n==1) {;save();}
|
||||||
|
if (cmd[0]=="speed" && n==3) {;v[i]=cut(icmd[2],FANMIN,FANMAX);err=0;}
|
||||||
|
if (cmd[0]=="bspeed" && n==3) {;b[i]=cut(icmd[2],FANMIN,FANMAX);err=0;}
|
||||||
|
if (cmd[0]=="btime" && n==3) {;btime[i]=cut(icmd[2],0,60);err=0;}
|
||||||
|
if (cmd[0]=="ctime" && n==3) {;ctime[i]=cut(icmd[2],60,240);err=0;}
|
||||||
|
if (cmd[0]=="rtime" && n==3) {;rtime[i]=cut(icmd[2],0,240);err=0;}
|
||||||
|
if (cmd[0]=="rnval" && n==3) {;rnval[i]=cut(icmd[2],0,1000);err=0;}
|
||||||
|
if (cmd[0]=="on" && n==2) {;fset(i,1);err=0;}
|
||||||
|
if (cmd[0]=="off" && n==2) {;fset(i,0);err=0;}
|
||||||
|
if (cmd[0]=="bon" && n==2) {;bset(i,1);err=0;}
|
||||||
|
if (cmd[0]=="boff" && n==2) {;bset(i,0);err=0;}
|
||||||
|
if (cmd[0]=="con" && n==2) {;cat[i]=1;catts[i]=MS;err=0;}
|
||||||
|
if (cmd[0]=="coff" && n==2) {;cat[i]=0;catts[i]=MS;err=0;}
|
||||||
|
if (cmd[0]=="otime" && n==3) {;oset(i,icmd[2]);err=0;}
|
||||||
|
|
||||||
|
updatelcd();
|
||||||
|
for (int i=0;i<2;i++) {
|
||||||
|
SX(F[i]);SX(":"); // 0, 16
|
||||||
|
SX((int)(v[i]));SX(":"); // 1, 17
|
||||||
|
SX((int)(b[i]));SX(":"); // 2, 18
|
||||||
|
SX(rpm[i]);SX(":"); // 3, 19
|
||||||
|
SX(xpm[i]);SX(":"); // 4, 20
|
||||||
|
SX(r[i]);SX(":"); // 5, 21
|
||||||
|
SX(bstate[i]);SX(":"); // 6, 22
|
||||||
|
SX(btime[i]);SX(":"); // 7, 23
|
||||||
|
SX(cat[i]);SX(":"); // 8, 24
|
||||||
|
SX(ctime[i]);SX(":"); // 9, 25
|
||||||
|
SX(rtime[i]);SX(":"); // 10, 26
|
||||||
|
SX(otime[i]);SX(":"); // 11, 27
|
||||||
|
SX(rnval[i]);SX(":"); // 12, 28
|
||||||
|
SX(rnd[i]);SX(":"); // 13, 29
|
||||||
|
if (bstate[i]) SX((((long)btime[i]*60000)-(MS-(long)bts[i]))/1000+1); else SX(0);SX(":"); // 14, 30
|
||||||
|
if (ostate[i]) SX((((long)otime[i]*3600000)-(MS-(long)ots[i]))/1000+1); else SX(0);SX(":"); // 15, 31
|
||||||
|
}
|
||||||
|
SX(VERSION);SX(":"); // 32
|
||||||
|
SX(MS);SX(":"); // 33
|
||||||
|
SXN(err); // 34
|
||||||
|
save();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SAVE>0 && MS-savets>SAVEDELAY) {;save();SAVE=0;savets=MS;} ////////////////////// save settings if needed
|
||||||
|
if (MS-savets>SAVEDELAY/5) bclr=1;
|
||||||
|
|
||||||
|
for (int i=0;i<2;i++) {
|
||||||
|
|
||||||
|
if (MS-rndts[i]>RNDINTERVAL) { /////////////////////////////////////////////////////////////// random timer
|
||||||
|
rnd[i]=int(random(0,rnval[i]+1)/10)*10;rndts[i]=MS;updatelcd();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ostate[i] && MS-ots[i]>(long)otime[i]*3600000) { ////////////////////////////////////// check off timer
|
||||||
|
otime[i]=0;ostate[i]=0;fset(i,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cat[i] && MS-catts[i]>(long)ctime[i]*60000 && F[i]==1) { //////////////////////////// initiate cat fish
|
||||||
|
catts[i]=MS;cstate[i]=1;F[i]=0;stop[i]=MS;updatePWM();updatespeed();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cstate[i] && MS-stop[i]>CATCHSTOP && F[i]==0) { ////////////////////////// stop cat fish and start over
|
||||||
|
cstate[i]=0;F[i]=1;vts[i]=MS;rts=MS+2000;updatePWM();updatespeed();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bstate[i] && MS-bts[i]>(long)btime[i]*60000) {;bstate[i]=0;S=0;updatelcd();} //////// check boost state
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MS-xts>SINTERVAL) { /////////////////////////////////////////////////////////////////// speed measurement
|
||||||
|
for (int i=0;i<2;i++) xpm[i]=xpm[i]*(SAVERAGE-1)/SAVERAGE+(bc[i]/((MS-xts)/1000.0)*30.0)/SAVERAGE;
|
||||||
|
updatespeed();xts=MS;bc[0]=0;bc[1]=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MS-rts>RINTERVAL) { //////////////////////////////////////////////////////////////////// speed regulation
|
||||||
|
for (int i=0;i<2;i++) {
|
||||||
|
rpm[i]=ac[i]/((MS-sts)/1000.0)*30.0;
|
||||||
|
ac[i]=0;
|
||||||
|
calcramp(i);
|
||||||
|
if (!F[i]) {;r[i]=0;setPWM(i,0);}
|
||||||
|
else {
|
||||||
|
q=(bstate[i]?xb[i]:xv[i])-rpm[i];
|
||||||
|
if (abs(q)>RTOL) r[i]=q<0?r[i]-1-abs(q)/10:r[i]+1+abs(q)/10;
|
||||||
|
setPWM(i,cut((bstate[i]?xb[i]:xv[i])/(FANMAX/320.0)+r[i],0,320));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sts=MS;rts=MS;
|
||||||
|
updatespeed();
|
||||||
|
}
|
||||||
|
|
||||||
|
bdelay=0; //////////////////////////////////////////////////////////////////////////////////// process switch
|
||||||
|
if (!bprocess) {
|
||||||
|
while (!digitalRead(SW)){
|
||||||
|
bdelay++;delay(15);bprocess=1;if (bdelay>20) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bdelay>0 && MS-buts>100) { // long button press
|
||||||
|
if (bdelay>20) {
|
||||||
|
|
||||||
|
if (M==2) { // lock/unlock
|
||||||
|
if (LOCK==0) LOCK=1;
|
||||||
|
else LOCK=0;
|
||||||
|
updatemarker();
|
||||||
|
} else {
|
||||||
|
if (S==0 && !LOCK) { // fan on/off
|
||||||
|
if (F[M]==0) fset(M,1); else fset(M,0);
|
||||||
|
}
|
||||||
|
if (S==1 && !LOCK) { // boost on/off
|
||||||
|
if (bstate[M]==0) bset(M,1); else {;bset(M,0);if (BOFF) fset(M,0);}
|
||||||
|
bclr=1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
save();updatespeed();bdelay=0;
|
||||||
|
|
||||||
|
} else if (bdelay>0 && bdelay<20 && !LOCK) { // short button press, switch: menu -> fan 0 -> fan 1
|
||||||
|
M++;if (S==8 && M==1) M=2;if (M>2) M=0;
|
||||||
|
updatemarker();
|
||||||
|
bdelay=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SAVE++;buts=MS;
|
||||||
|
}
|
||||||
|
if (digitalRead(SW)) bprocess=0;
|
||||||
|
|
||||||
|
encval = digitalRead(CLK); ////////////////////////////////////////////////////////////////// process encoder
|
||||||
|
if (encval != enclast && !LOCK) {
|
||||||
|
if(!encval){
|
||||||
|
|
||||||
|
if (digitalRead(DT) != encval) { // turn encoder clockwise
|
||||||
|
if (M==2) S++; // scroll menu
|
||||||
|
else {
|
||||||
|
if (S==0) v[M]+=SPEEDINC; // fan speed up
|
||||||
|
if (S==1) b[M]+=SPEEDINC; // boost speed up
|
||||||
|
if (S==2) btime[M]+=BINC; // boost time up
|
||||||
|
if (S==3) cat[M]++; // cat on/off
|
||||||
|
if (S==4) ctime[M]+=CINC; // cat time up
|
||||||
|
if (S==5) rtime[M]+=RINC; // rise time up
|
||||||
|
if (S==6) otime[M]+=OINC; // off time up
|
||||||
|
if (S==7) rnval[M]+=SPEEDINC; // random value
|
||||||
|
if (S==8) brght++; // increase LCD brightness
|
||||||
|
}
|
||||||
|
} else { // turn encoder counterclockwise
|
||||||
|
if (M==2) S--; // scroll menu
|
||||||
|
else {
|
||||||
|
if (S==0) v[M]-=SPEEDINC; // fan speed down
|
||||||
|
if (S==1) b[M]-=SPEEDINC; // boost speed down
|
||||||
|
if (S==2) btime[M]-=BINC; // boost time down
|
||||||
|
if (S==3) cat[M]--; // cat on/off
|
||||||
|
if (S==4) ctime[M]-=CINC; // cat time down
|
||||||
|
if (S==5) rtime[M]-=RINC; // rise time down
|
||||||
|
if (S==6) otime[M]-=OINC; // off time down
|
||||||
|
if (S==7) rnval[M]-=SPEEDINC; // random value
|
||||||
|
if (S==8) brght--; // decrease LCD brightness
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i=0;i<2;i++) if (b[i]<v[i]) b[i]=v[i];
|
||||||
|
|
||||||
|
if (M!=2) {
|
||||||
|
if (S<=1) {;updatePWM();rts=MS+RDELAY;} // apply (boost) speed change
|
||||||
|
if (S==2) btime[M]=cut(btime[M],0,99); // check boost time
|
||||||
|
if (S==3) {;cat[M]=cut(cat[M],0,1);catts[M]=MS;} // check cat
|
||||||
|
if (S==4) ctime[M]=cut(ctime[M],60,240); // check cat time
|
||||||
|
if (S==5) rtime[M]=cut(rtime[M],0,240); // check rise time
|
||||||
|
if (S==6) oset(M,otime[M]); // check off time
|
||||||
|
if (S==7) {;rnval[M]=cut(rnval[M],0,1000);updatePWM();} // apply random value change
|
||||||
|
if (S==8) lset(); // set LCD brightness
|
||||||
|
}
|
||||||
|
|
||||||
|
if (M==2) S=cut(S,0,8); // check menu mode
|
||||||
|
|
||||||
|
SAVE++;updatelcd();delay(25);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enclast=encval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////// SUPPORT
|
||||||
|
|
||||||
|
void lset() { ////////////////////////////////////////////////////////////////////////////// set LCD brightness
|
||||||
|
brght=cut(brght,0,9);
|
||||||
|
analogWrite(PWM2,LCDB[brght]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void oset(int n,int t) { ///////////////////////////////////////////////////////////////// set switch off timer
|
||||||
|
otime[n]=cut(t,0,99);ots[n]=MS;ostate[n]=otime[n]?1:0;
|
||||||
|
SAVE++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fset(int n,int s) { /////////////////////////////////////////////////////////////// set fan state (on/off)
|
||||||
|
if (s==1) {
|
||||||
|
rts=MS+RDELAY;F[n]=1;catts[n]=vts[n]=MS;r[n]=0;
|
||||||
|
} else {
|
||||||
|
F[n]=0;bstate[n]=0;
|
||||||
|
}
|
||||||
|
updatePWM();
|
||||||
|
SAVE++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bset(int n,int s) { ///////////////////////////////////////////////////////////// set boost state (on/off)
|
||||||
|
if (s==1) {
|
||||||
|
rts=MS+RDELAY;bstate[n]=1;bts[n]=MS;F[n]=1;vts[n]=MS;
|
||||||
|
} else {
|
||||||
|
bstate[n]=0;rts=MS+RDELAY;
|
||||||
|
}
|
||||||
|
updatePWM();
|
||||||
|
SAVE++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void updatelcd() { ///////////////////////////////////////////////////////////////////////////////// update LCD
|
||||||
|
for (int i=0;i<2;i++) {
|
||||||
|
if (S==0) {;slcd(1,1,5,"SPEED");ilcd(7+i*5,1,-4,v[i]);}
|
||||||
|
if (S==1) {;slcd(1,1,5,"BOOST");ilcd(7+i*5,1,-4,int(b[i]));}
|
||||||
|
if (S==2) {;slcd(1,1,5,"BTIME");ilcd(7+i*5,1,-4,int(btime[i]));}
|
||||||
|
if (S==3) {
|
||||||
|
slcd(1,1,5,"CATCH");
|
||||||
|
if (cat[i]==0) slcd( 7+i*5,1,-4,"OFF"); else slcd( 7+i*5,1,-3,"ON");
|
||||||
|
}
|
||||||
|
if (S==4) {;slcd(1,1,5,"CTIME");ilcd(7+i*5,1,-4,int(ctime[i]));}
|
||||||
|
if (S==5) {;slcd(1,1,5,"RTIME");ilcd(7+i*5,1,-4,int(rtime[i]));}
|
||||||
|
if (S==6) {;slcd(1,1,5,"OTIME");ilcd(7+i*5,1,-4,int(otime[i]));}
|
||||||
|
if (S==7) {;slcd(1,1,5,"RNVAL");ilcd(7+i*5,1,-4,int(rnval[i]));}
|
||||||
|
}
|
||||||
|
if (S==8) {;slcd(1,1,5,"BRGHT");ilcd(7,1,-4,brght);slcd(7+5,1,-4," ");}
|
||||||
|
}
|
||||||
|
|
||||||
|
void updatemarker() { ////////////////////////////////////////////////////////////////////// update menu marker
|
||||||
|
slcd(0,1,1," ");slcd(6,1,1," ");slcd(11,1,1," ");
|
||||||
|
int m[]={6,11,0};if (!LOCK) clcd(m[M],1,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void updatespeed() { ///////////////////////////////////////////////////////////////////////// update fan speed
|
||||||
|
if (bclr) slcd(0,0,6," ");
|
||||||
|
for (int i=0;i<2;i++) {
|
||||||
|
slcd(6+i*5,0,1," ");
|
||||||
|
if (cstate[i]) slcd(7+i*5,0,-4,"CAT");
|
||||||
|
else {
|
||||||
|
if (F[i]) {
|
||||||
|
if (bstate[i]) ilcd(1+i*3,0,-2, (((long)btime[i]*60000)-(MS-(long)bts[i]))/1000/60+1);
|
||||||
|
else if (ostate[i]) ilcd(1+i*3,0,-2, (((long)otime[i]*3600000)-(MS-(long)ots[i]))/1000/60/60+1);
|
||||||
|
ilcd(7+i*5,0,-4,round(xpm[i]));
|
||||||
|
if ((!bstate[i] && xv[i]<v[i]) || (bstate[i] && xb[i]<b[i])) clcd(6+i*5,0,1);
|
||||||
|
else {
|
||||||
|
if (xv[i]>=v[i] && rnval[i]>0 && !bstate[i]) clcd(6+i*5,0,2);
|
||||||
|
}
|
||||||
|
} else slcd(7+i*5,0,-4,"OFF");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void clcd(int x,int y, char v) { /////////////////////////////////////////////////////// write character to LCD
|
||||||
|
lcd.setCursor(x,y);lcd.write(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ilcd(int x,int y, int l,int v) { //////////////////////////////////////////////////// write integer to LCD
|
||||||
|
sprintf(form,"%%%dd",l);sprintf(out,form,v);lcd.setCursor(x,y);lcd.print(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
void slcd(int x,int y, int l,String s) { ////////////////////////////////////////////////// write string to LCD
|
||||||
|
sprintf(form,"%%%ds",l);sprintf(out,form,s.c_str());lcd.setCursor(x,y);lcd.print(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
void calcramp(int i) { ///////////////////////////////////////////////////////////// calculate speed ramp value
|
||||||
|
xb[i]=b[i];
|
||||||
|
int rt=rtime[i]?rtime[i]:1;
|
||||||
|
if (bstate[i]) xb[i]=cut(((b[i]-v[i])/(rt*1000.0)*(MS-bts[i]))+v[i],v[i],b[i]);
|
||||||
|
xv[i]=v[i];
|
||||||
|
xv[i]=cut(((v[i]-FANMIN)/(rt*1000.0)*(MS-vts[i]))+FANMIN,FANMIN,v[i]);
|
||||||
|
if (rnval[i]>0 && xv[i]>=v[i]) xv[i]=cut(xv[i]+rnd[i],FANMIN,FANMAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setPWM(int n,int v) { /////////////////////////////////////////// set value to OCR1x and states to off pin
|
||||||
|
if (n==0) {
|
||||||
|
OCR1A=v;
|
||||||
|
if (v==0) digitalWrite(OFF0,OFFSTATE?HIGH:LOW);
|
||||||
|
else digitalWrite(OFF0,OFFSTATE?LOW:HIGH);
|
||||||
|
}
|
||||||
|
if (n==1) {
|
||||||
|
OCR1B=v;
|
||||||
|
if (v==0) digitalWrite(OFF1,OFFSTATE?HIGH:LOW);
|
||||||
|
else digitalWrite(OFF1,OFFSTATE?LOW:HIGH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void updatePWM() { ////////////////////////////////////////////////////////////// update PWM output (fan speed)
|
||||||
|
for (int i=0;i<2;i++) {
|
||||||
|
v[i]=cut(v[i],FANMIN,FANMAX);
|
||||||
|
b[i]=cut(b[i],FANMIN,FANMAX);
|
||||||
|
calcramp(i);
|
||||||
|
if (!F[i]) setPWM(i,0); else setPWM(i,cut((bstate[i]?xb[i]:xv[i])/(FANMAX/320.0)+r[i],0,320));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void rpmint0() {;ac[0]++;bc[0]++;} ///////////////////////////////////////////////////////////// rpm interrupts
|
||||||
|
void rpmint1() {;ac[1]++;bc[1]++;}
|
||||||
|
|
||||||
|
double cut(double v,double min,double max) {;return v>max?max:v<min?min:v>max?max:v;} ///// cut values to limit
|
||||||
|
|
||||||
|
int eer(int adr) {;return EEPROM.read(adr*2)+EEPROM.read(adr*2+1)*256;} /////////////////////////// read EEPROM
|
||||||
|
|
||||||
|
void eew(int adr, int val) {;EEPROM.write(adr*2,val%256);EEPROM.write(adr*2+1,val/256);} /////// save to EEPROM
|
||||||
|
|
||||||
|
void save() { /////////////////////////////////////////////////////////////////////////////////// save settings
|
||||||
|
for (int i=0;i<2;i++) {
|
||||||
|
eew(1+i,v[i]);eew(3+i,b[i]);eew(5+i,btime[i]);eew(7+i,cat[i]);
|
||||||
|
eew(9+i,ctime[i]);eew(11+i,F[i]);eew(13+i,rtime[i]);eew(15+i,rnval[i]);
|
||||||
|
}
|
||||||
|
eew(100,seed);
|
||||||
|
eew(101,brght);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cutcmd(String data) { ///////////////////////////////////////////////////////////// get saperated substring
|
||||||
|
int mi=data.length(),n=0,j=0;
|
||||||
|
for (int i=0;i<=mi;i++) {
|
||||||
|
if (data.charAt(i) == ':' || i == mi) {;cmd[n]=data.substring(j,i);j=i+1;n++;}
|
||||||
|
}
|
||||||
|
for (int i=1;i<n;i++) icmd[i]=cmd[i].toInt();
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////// END
|
70
V1 (old)/stirctl
Executable file
@ -0,0 +1,70 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
###################################################################################### stir controll (mwx'2019)
|
||||||
|
use Device::SerialPort;
|
||||||
|
use Time::HiRes qw( usleep );
|
||||||
|
|
||||||
|
$dev='/dev/ttyACM0';
|
||||||
|
|
||||||
|
my $port = Device::SerialPort->new($dev); ################################################### setup serial port
|
||||||
|
|
||||||
|
$port->baudrate(9600);
|
||||||
|
$port->databits(8);
|
||||||
|
$port->parity("none");
|
||||||
|
$port->stopbits(1);
|
||||||
|
|
||||||
|
$port->lookfor();
|
||||||
|
|
||||||
|
$cmd=join(':',@ARGV);$cmd='info' if ($cmd=~/^\s*$/);
|
||||||
|
|
||||||
|
@r=split(':',&scmd($cmd));
|
||||||
|
|
||||||
|
print " LEFT RIGHT\n";
|
||||||
|
printf("Stirrer On: %6d %6d\n", $r[0],$r[16]);
|
||||||
|
printf("Speed: %6d %6d\n", $r[1],$r[17]);
|
||||||
|
printf("Boost Speed: %6d %6d\n", $r[2],$r[18]);
|
||||||
|
printf("RPM: %6d %6d\n", $r[3],$r[19]);
|
||||||
|
printf("Average RPM: %6d %6d\n", $r[4],$r[20]);
|
||||||
|
printf("Regulation: %6d %6d\n", $r[5],$r[21]);
|
||||||
|
printf("Boost On: %6d %6d\n", $r[6],$r[22]);
|
||||||
|
printf("Boost Time: %6d %6d\n", $r[7],$r[23]);
|
||||||
|
printf("Catch On: %6d %6d\n", $r[8],$r[24]);
|
||||||
|
printf("Catch Time: %6d %6d\n", $r[9],$r[25]);
|
||||||
|
printf("Rise Time: %6d %6d\n", $r[10],$r[26]);
|
||||||
|
printf("Off Time: %6d %6d\n", $r[11],$r[27]);
|
||||||
|
printf("Random Range: %6d %6d\n", $r[12],$r[28]);
|
||||||
|
printf("Random Value: %6d %6d\n", $r[13],$r[29]);
|
||||||
|
printf("Boost Remain: %6d %6d\n", $r[14],$r[30]);
|
||||||
|
printf("Off Remain: %6d %6d\n", $r[15],$r[31]);
|
||||||
|
|
||||||
|
printf("VERSION: %s\n",$r[32]);
|
||||||
|
printf("UPTIME: %s\n",&dhms($r[33]/1000));
|
||||||
|
printf("ERROR: %d\n",$r[34]);
|
||||||
|
|
||||||
|
sub scmd() { ##################################################################################### send command
|
||||||
|
my($cmd,$quiet)=@_;
|
||||||
|
|
||||||
|
$port->write($cmd);
|
||||||
|
my $founddata=0;
|
||||||
|
$msg="";
|
||||||
|
for ($i=0;$i<1000;$i++) {
|
||||||
|
|
||||||
|
$in = $port->lookfor();
|
||||||
|
$founddata=1 if ($in ne "");
|
||||||
|
$msg.=$in;
|
||||||
|
|
||||||
|
last if ($in eq "" && $founddata);
|
||||||
|
|
||||||
|
&usleep(2500);
|
||||||
|
}
|
||||||
|
|
||||||
|
$msg=~s/[\r\n]+//g;
|
||||||
|
return $msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub dhms { ######################################################################## convert secs to dd:hh:mm:ss
|
||||||
|
my($t)=@_;my ($d,$h,$m,$s);
|
||||||
|
$s=$t%60;$t=($t-$s)/60;$m=$t%60;$t=($t-$m)/60;$h=$t%24;$t=($t-$h)/24;$d=$t;
|
||||||
|
return sprintf("%d:%02d:%02d:%02d",$d,$h,$m,$s);
|
||||||
|
}
|
||||||
|
|
||||||
|
########################################################################################################### END
|
BIN
cad/bezel@herbert/Magnetaufnahme Rührer Wing3_V2.0.stl
Normal file
BIN
cad/bezel@herbert/Magnetaufnahme Rührer Wing3_V3.0.stl
Normal file
@ -1,52 +0,0 @@
|
|||||||
$fn=128;
|
|
||||||
|
|
||||||
g = 10; // magnet gap
|
|
||||||
|
|
||||||
fw = 48.3; // fan width
|
|
||||||
|
|
||||||
h = 4; // base height
|
|
||||||
r = 5; // edge width
|
|
||||||
|
|
||||||
pn = 7; // number of pins
|
|
||||||
ph = 7; // pin height
|
|
||||||
pa = 20; // pin angle
|
|
||||||
|
|
||||||
mw = 10.25; // magnet width
|
|
||||||
ml = 20.25; // magnet length
|
|
||||||
mb = 17; // magnet bar width
|
|
||||||
|
|
||||||
d=fw+r+r; // total diameter
|
|
||||||
cl=d-r; // magnet bar length
|
|
||||||
a=360/pn; // segment angle
|
|
||||||
e=(d+g-10)/d; // elliptic scale factor
|
|
||||||
|
|
||||||
difference() {
|
|
||||||
union() {
|
|
||||||
difference() {
|
|
||||||
union() {
|
|
||||||
translate([0,0,0]) cylinder(h+ph,d/2,d/2);
|
|
||||||
translate([0,0,0]) scale([e, 1, 1]) cylinder(h,d/2,d/2);
|
|
||||||
}
|
|
||||||
translate([0,0,-1]) cylinder(h+ph+2,d/2-r,d/2-r);
|
|
||||||
for (i =[0:1:pn-1]) {
|
|
||||||
pin(a*i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
translate([-cl/2,-mb/2,0]) cube([cl,mb,h]);
|
|
||||||
rotate ([0,0,90]) translate([-cl/2,-(mb-mw)/4-d/7,0]) cube([cl,(mb-mw)/2,h]);
|
|
||||||
rotate ([0,0,90]) translate([-cl/2,-(mb-mw)/4+d/7,0]) cube([cl,(mb-mw)/2,h]);
|
|
||||||
}
|
|
||||||
translate([-ml-g/2,-mw/2,-1]) cube([ml,mw,h]);
|
|
||||||
translate([g/2,-mw/2,-1]) cube([ml,mw,h]);
|
|
||||||
}
|
|
||||||
|
|
||||||
module pin(r) {
|
|
||||||
translate([0,0,0.01]) rotate([0,0,r]) hull() {
|
|
||||||
translate([0,0,h]) cylinder(h+ph,0.1,0.1);
|
|
||||||
translate([-d,0,h]) cylinder(h+ph,0.1,0.1);
|
|
||||||
rotate ([0,0,a-pa])union() {
|
|
||||||
translate([0,0,h]) cylinder(h+ph,0.1,0.1);
|
|
||||||
translate([-d,0,h]) cylinder(h+ph,0.1,0.1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +1,7 @@
|
|||||||
# CAD Files
|
# CAD Files
|
||||||
|
|
||||||
CAD files for 3D printed magnet holder. Compatible for magnets with size 20x10x5 mm and
|
CAD files for 3D printed magnet moun. Compatible for magnets with size 20x10x5 mm and
|
||||||
*be quiet! Silent Wings 3 140 mm* fans.
|
*be quiet! Silent Wings 3 120/140 mm* fans.
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="https://github.com/micworg/stir/blob/master/images/magnetmount.jpg" width=500>
|
<img src="https://github.com/micworg/stir/blob/master/images/magnetmount.jpg" width=500>
|
57
cad/magnetmount/magnetmount.scad
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/// magnet mount for for magnets with size 20x10x5 mm and be quiet! Silent Wings 3 120/140 mm fans
|
||||||
|
|
||||||
|
$fn=128;
|
||||||
|
|
||||||
|
g = 10; // magnet gap
|
||||||
|
fan = 120; // fan size (120 or 140)
|
||||||
|
|
||||||
|
h = 4; // base height
|
||||||
|
r = 5; // edge width
|
||||||
|
|
||||||
|
pn = 7; // number of pins
|
||||||
|
ph = 7; // pin height
|
||||||
|
pa = 20; // pin angle
|
||||||
|
|
||||||
|
mw = 10.25; // magnet width
|
||||||
|
ml = 20.25; // magnet length
|
||||||
|
mb = 17; // magnet bar width
|
||||||
|
|
||||||
|
fw= fan==140 ? 48.3 : 42.5; // fan center width
|
||||||
|
eo= fan==140 ? 10 : 5; // elliptic extra offset
|
||||||
|
|
||||||
|
d=fw+r+r; // total diameter
|
||||||
|
cl=d-r; // magnet bar length
|
||||||
|
a=360/pn; // segment angle
|
||||||
|
e=(d+g-eo)/d; // elliptic scale factor
|
||||||
|
|
||||||
|
|
||||||
|
difference() {
|
||||||
|
union() {
|
||||||
|
difference() {
|
||||||
|
union() {
|
||||||
|
translate([0,0,0]) cylinder(h+ph,d/2,d/2);
|
||||||
|
translate([0,0,0]) scale([e, 1, 1]) cylinder(h,d/2,d/2);
|
||||||
|
}
|
||||||
|
translate([0,0,-1]) cylinder(h+ph+2,d/2-r,d/2-r);
|
||||||
|
for (i =[0:1:pn-1]) {
|
||||||
|
pin(a*i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
translate([-cl/2,-mb/2,0]) cube([cl,mb,h]);
|
||||||
|
rotate ([0,0,90]) translate([-cl/2,-(mb-mw)/4-d/7,0]) cube([cl,(mb-mw)/2,h]);
|
||||||
|
rotate ([0,0,90]) translate([-cl/2,-(mb-mw)/4+d/7,0]) cube([cl,(mb-mw)/2,h]);
|
||||||
|
}
|
||||||
|
translate([-ml-g/2,-mw/2,-1]) cube([ml,mw,h]);
|
||||||
|
translate([g/2,-mw/2,-1]) cube([ml,mw,h]);
|
||||||
|
}
|
||||||
|
|
||||||
|
module pin(r) {
|
||||||
|
translate([0,0,0.01]) rotate([0,0,r]) hull() {
|
||||||
|
translate([0,0,h]) cylinder(h+ph,0.1,0.1);
|
||||||
|
translate([-d,0,h]) cylinder(h+ph,0.1,0.1);
|
||||||
|
rotate ([0,0,a-pa])union() {
|
||||||
|
translate([0,0,h]) cylinder(h+ph,0.1,0.1);
|
||||||
|
translate([-d,0,h]) cylinder(h+ph,0.1,0.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12434
cad/magnetmount/magnetmount120x10.stl
Normal file
12434
cad/magnetmount/magnetmount120x20.stl
Normal file
BIN
images/pcb_top.jpg
Normal file
After Width: | Height: | Size: 111 KiB |
BIN
images/stir+pcb.jpg
Normal file
After Width: | Height: | Size: 295 KiB |
BIN
images/v2_board.jpg
Normal file
After Width: | Height: | Size: 412 KiB |
307
stir.ino
@ -1,84 +1,125 @@
|
|||||||
/////////////////////////////////////////////////////////////////////////////////////// Stir Control (mwx'2019)
|
//////////////////////////////////////////////////////////////////////////////////// Stir Control V2 (mwx'2019)
|
||||||
#include <EEPROM.h>
|
#include <EEPROM.h>
|
||||||
#include <LiquidCrystal_I2C.h>
|
#include <LiquidCrystal_I2C.h>
|
||||||
|
|
||||||
#define MS (long)millis()
|
#define MS (long)millis()
|
||||||
|
#define NP 25
|
||||||
|
|
||||||
#define SX Serial.print
|
String VERSION = "2.1.2";
|
||||||
#define SXN Serial.println
|
|
||||||
|
|
||||||
String VERSION = "1.7.0";
|
int FANINIT = 0; // initialize fan with high voltage (0/1)
|
||||||
|
|
||||||
int SPEEDINC = 50; // speed increment (rpm)
|
int SPEEDINC1 = 20; // speed increment values
|
||||||
|
int SPEEDINC2 = 50;
|
||||||
|
int SPEEDINC3 = 100;
|
||||||
|
|
||||||
|
int SPEEDSTEP1 = 400; // speed increment steps (increment changes at these values)
|
||||||
|
int SPEEDSTEP2 = 1000;
|
||||||
|
|
||||||
|
int RNDINC = 50; // random value increment (rpm)
|
||||||
|
|
||||||
int FANMIN = 200; // fan minimum speed (should be a value at which the fan runs safely) (rpm)
|
int FANMIN = 200; // fan minimum speed (should be a value at which the fan runs safely) (rpm)
|
||||||
int FANMAX = 1600; // fan maximum speed (should be the real maximum value of the fan) (rpm)
|
int FANMAX = 2500; // fan maximum speed (should be the real maximum value of the fan) (rpm)
|
||||||
|
|
||||||
int BOFF = 0; // if set boost off will also turn the normal mode off
|
int BOFF = 0; // if set boost off will also turn the normal mode off (0/1)
|
||||||
|
|
||||||
int BINC = 1; // BTIME increment (min)
|
int BINC = 1; // BTIME increment (min)
|
||||||
int CINC = 10; // CTIME increment (min)
|
int CINC = 10; // CTIME increment (min)
|
||||||
int RINC = 10; // RTIME increment (sec)
|
int RINC = 10; // RTIME increment (sec)
|
||||||
int OINC = 3; // OTIME increment (hour)
|
int OINC = 3; // OTIME increment (hour)
|
||||||
|
|
||||||
long CATCHSTOP = 20000; // fish catch stop period (ms)
|
int CATCHSTOP = 20; // fish catch stop period (sec)
|
||||||
|
|
||||||
int PWM0 = 9; // PWM pin for 1. fan
|
int PWM0 = 9; // PWM pin for 1. fan
|
||||||
int PWM1 = 10; // PWM pin for 2. fan
|
int PWM1 = 10; // PWM pin for 2. fan
|
||||||
int PWM2 = 11; // PWM pin for LCD brightness
|
int PWM2 = 11; // PWM pin for LCD brightness
|
||||||
|
|
||||||
int I0 = 2; // interrupt for fan 0 rpm signal (use 2 for Leonardo/ProMicro and 0 for Uno)
|
int I0 = 0; // interrupt for fan 0 rpm signal (use 2 for Leonardo/ProMicro and 0 for Uno)
|
||||||
int I1 = 3; // interrupt for fan 1 rpm signal (use 3 for Leonardo/ProMicro and 1 for Uno)
|
int I1 = 1; // interrupt for fan 1 rpm signal (use 3 for Leonardo/ProMicro and 1 for Uno)
|
||||||
|
|
||||||
int CLK = 5; // clk on KY-040 encoder
|
int SWAPENC = 1; // swap encoder direction
|
||||||
|
|
||||||
|
int CLK = 5; // clk on KY-040 encoder (swap clk and dt to invert direction)
|
||||||
int DT = 6; // dt on KY-040 encoder
|
int DT = 6; // dt on KY-040 encoder
|
||||||
int SW = 4; // sw on KY-040 encoder
|
int SW = 4; // sw on KY-040 encoder
|
||||||
|
|
||||||
int OFF0 = 7; // off state pin 1. fan
|
int R0 = 7; // voltage select relais 0
|
||||||
int OFF1 = 8; // off state pin 2. fan
|
int R1 = 8; // voltage select relais 1
|
||||||
int OFFSTATE = LOW; // off state (LOW/HIGH)
|
int RTHRES = 700; // voltage switch threshold (rpm)
|
||||||
|
|
||||||
long RINTERVAL = 5000; // regulation internval (ms)
|
int RINTERVAL = 50; // regulation internval (ds)
|
||||||
long RDELAY = 3000; // regulation delay on changes (ms)
|
int RDELAY = 30; // regulation delay on changes (ds)
|
||||||
int RTOL = 8; // regulation tolerance (rpm)
|
int RTOL = 8; // regulation tolerance (rpm)
|
||||||
|
|
||||||
long RNDINTERVL = 300000; // randon value change interval
|
int RNDINTERVAL = 300; // randon value range change interval (sec)
|
||||||
|
|
||||||
long SINTERVAL = 2000; // speed measurement internval
|
int SINTERVAL = 20; // speed measurement internval (ds)
|
||||||
int SAVERAGE = 4; // speed measurement average
|
int SAVERAGE = 4; // speed measurement average
|
||||||
|
|
||||||
int SAVETAG = 1014; // save tag
|
int SAVETAG = 2017; // save tag
|
||||||
long SAVEDELAY = 10000; // EEPROM save delay (ms)
|
long SAVEDELAY = 10000; // EEPROM save delay (ms)
|
||||||
|
|
||||||
|
int RESET = 0; // factory reset, DON'T CHANGE THIS HERE (used from configuration menu)
|
||||||
|
|
||||||
|
int LGHT = 5; // LCD brightness
|
||||||
|
|
||||||
byte LCDB[] = {4,8,16,24,32,64,96,128,192,255}; // LCD brightness steps (10 values, 0=off, 255=max)
|
byte LCDB[] = {4,8,16,24,32,64,96,128,192,255}; // LCD brightness steps (10 values, 0=off, 255=max)
|
||||||
|
|
||||||
byte aright[] = {0x00,0x08,0x0C,0x0E,0x0C,0x08,0x00,0x00}; // LCD character
|
byte aright[] = {0x00,0x08,0x0C,0x0E,0x0C,0x08,0x00,0x00}; // LCD character
|
||||||
byte aup[] = {0x04,0x0E,0x1F,0x00,0x00,0x00,0x00,0x00};
|
byte aup[] = {0x04,0x0E,0x1F,0x00,0x00,0x00,0x00,0x00};
|
||||||
byte arnd[] = {0x0E,0x0E,0x0E,0x00,0x00,0x00,0x00,0x00};
|
byte arnd[] = {0x0E,0x0E,0x0E,0x00,0x00,0x00,0x00,0x00};
|
||||||
|
|
||||||
|
|
||||||
LiquidCrystal_I2C lcd(0x27,16,2); // LCD display (connect to SDA/SCL)
|
LiquidCrystal_I2C lcd(0x27,16,2); // LCD display (connect to SDA/SCL)
|
||||||
|
|
||||||
int v[2],b[2],r[2]={0};double q,rpm[2]={0},xpm[2]={0},xb[2]={0},xv[2]={0},rtime[2]; // speed and regulation
|
int v[2],b[2],r[2]={0};double q,rpm[2]={0},xpm[2]={0},xb[2]={0},xv[2]={0},rtime[2]; // speed and regulation
|
||||||
long ac[2]={0},bc[2]={0}; // interrupt rpm counter
|
long ac[2]={0},bc[2]={0}; // interrupt rpm counter
|
||||||
long xts,sts,rts,swts,buts,savets,catts[2],stop[2],bts[2],vts[2],ots[2],rndts[2]; // timing
|
long xts,sts,rts,swts,buts,savets,catts[2],stop[2],bts[2],vts[2],ots[2],rndts[2]; // timing
|
||||||
int bdelay,bprocess=0,enclast,encval,M=2,S=0; // button/encoder processing
|
int bdelay,bprocess=0,enclast,encval,M=2,S=0,C=0; // button/encoder processing
|
||||||
int F[2],bstate[2]={0},btime[2],cat[2],ctime[2],cstate[2]={0},bclr=0,SAVE=0,LOCK=0; // operating states
|
int F[2],bstate[2]={0},btime[2],cat[2],ctime[2],cstate[2]={0},bclr=0,SAVE=0,LOCK=0; // operating states
|
||||||
int ostate[2]={0},otime[2]={0}; // off timer
|
int ostate[2]={0},otime[2]={0}; // off timer
|
||||||
int brght; // LCD brightness
|
|
||||||
int rnd[2]={0},rnval[2]={0};long seed; // random speed
|
int rnd[2]={0},rnval[2]={0};long seed; // random speed
|
||||||
char form[8],out[20];String cmd[8];int icmd[8]; // string buffer
|
char form[8],out[20]; // string buffer
|
||||||
|
String CF[NP];int *P[NP],Cinc[NP],Cmin[NP],Cmax[NP]; // configuration menu
|
||||||
|
int clkorg,dtorg; // encoder direction
|
||||||
|
|
||||||
|
void(* resetFunc) (void) = 0;
|
||||||
|
|
||||||
void setup() { ////////////////////////////////////////////////////////////////////////////////////////// SETUP
|
void setup() { ////////////////////////////////////////////////////////////////////////////////////////// SETUP
|
||||||
Serial.begin(9600); // start serial
|
|
||||||
|
int i=0;
|
||||||
|
|
||||||
|
P[i]=&LGHT; CF[i]=F("LGHT"); defcon(i, 1, 0, 9 ); i++;
|
||||||
|
P[i]=&SPEEDINC1; CF[i]=F("SPI1"); defcon(i, 10, 10, 500 ); i++;
|
||||||
|
P[i]=&SPEEDINC2; CF[i]=F("SPI2"); defcon(i, 10, 10, 500 ); i++;
|
||||||
|
P[i]=&SPEEDINC3; CF[i]=F("SPI3"); defcon(i, 10, 10, 500 ); i++;
|
||||||
|
P[i]=&SPEEDSTEP1; CF[i]=F("SPS1"); defcon(i, 50, 100, 2000 ); i++;
|
||||||
|
P[i]=&SPEEDSTEP2; CF[i]=F("SPS2"); defcon(i, 50, 100, 2000 ); i++;
|
||||||
|
P[i]=&SWAPENC; CF[i]=F("SWEN"); defcon(i, 1, 0, 1 ); i++;
|
||||||
|
P[i]=&RNDINC; CF[i]=F("RINC"); defcon(i, 1, 0, 9 ); i++;
|
||||||
|
P[i]=&CATCHSTOP; CF[i]=F("CSTP"); defcon(i, 10, 0, 1000 ); i++;
|
||||||
|
P[i]=&FANMIN; CF[i]=F("FMIN"); defcon(i, 50, 100, 1000 ); i++;
|
||||||
|
P[i]=&FANMAX; CF[i]=F("FMAX"); defcon(i, 50, 500, 4000 ); i++;
|
||||||
|
P[i]=&FANINIT; CF[i]=F("FINI"); defcon(i, 1, 0, 1 ); i++;
|
||||||
|
P[i]=&RTHRES; CF[i]=F("RTHR"); defcon(i, 50, 0, 1500 ); i++;
|
||||||
|
P[i]=&RNDINTERVAL; CF[i]=F("RINT"); defcon(i, 1, 0, 60 ); i++;
|
||||||
|
P[i]=&BOFF; CF[i]=F("BOFF"); defcon(i, 1, 0, 1 ); i++;
|
||||||
|
P[i]=&BINC; CF[i]=F("BINC"); defcon(i, 1, 1, 60 ); i++;
|
||||||
|
P[i]=&CINC; CF[i]=F("CINC"); defcon(i, 1, 1, 60 ); i++;
|
||||||
|
P[i]=&RINC; CF[i]=F("RINC"); defcon(i, 1, 1, 60 ); i++;
|
||||||
|
P[i]=&OINC; CF[i]=F("OINC"); defcon(i, 1, 1, 60 ); i++;
|
||||||
|
P[i]=&RINTERVAL; CF[i]=F("XINT"); defcon(i, 1, 10, 250 ); i++;
|
||||||
|
P[i]=&RDELAY; CF[i]=F("XDEL"); defcon(i, 1, 0, 100 ); i++;
|
||||||
|
P[i]=&RTOL; CF[i]=F("XTOL"); defcon(i, 1, 1, 100 ); i++;
|
||||||
|
P[i]=&SINTERVAL; CF[i]=F("SINT"); defcon(i, 1, 0, 100 ); i++;
|
||||||
|
P[i]=&SAVERAGE; CF[i]=F("SAVG"); defcon(i, 1, 1, 100 ); i++;
|
||||||
|
P[i]=&RESET; CF[i]=F("RSET"); defcon(i, 1, 0, 1 ); i++;
|
||||||
|
|
||||||
lcd.init();lcd.clear();lcd.backlight(); // initialize lcd
|
lcd.init();lcd.clear();lcd.backlight(); // initialize lcd
|
||||||
lcd.createChar(0,aright);lcd.createChar(1,aup);lcd.createChar(2,arnd); // load lcd characters
|
lcd.createChar(0,aright);lcd.createChar(1,aup);lcd.createChar(2,arnd); // load lcd characters
|
||||||
pinMode(PWM0,OUTPUT);pinMode(PWM1,OUTPUT);pinMode(PWM2,OUTPUT); // setup PWM pins
|
pinMode(PWM0,OUTPUT);pinMode(PWM1,OUTPUT);pinMode(PWM2,OUTPUT); // setup PWM pins
|
||||||
pinMode(CLK,INPUT);pinMode(DT,INPUT);pinMode(SW,INPUT); // setup KY-040 pins
|
pinMode(CLK,INPUT);pinMode(DT,INPUT);pinMode(SW,INPUT); // setup KY-040 pins
|
||||||
digitalWrite(CLK,true);digitalWrite(DT,true);digitalWrite(SW,true); // turn ON pullup resistors
|
digitalWrite(CLK,true);digitalWrite(DT,true);digitalWrite(SW,true); // turn ON pullup resistors
|
||||||
pinMode(OFF0,OUTPUT);pinMode(OFF1,OUTPUT); // setup off state pins
|
pinMode(R0,OUTPUT);pinMode(R1,OUTPUT); // setup voltage selcet relais pins
|
||||||
|
|
||||||
attachInterrupt(I0,rpmint0,FALLING); // setup interrupts vor rpm in
|
attachInterrupt(I0,rpmint0,FALLING); // setup interrupts vor rpm in
|
||||||
attachInterrupt(I1,rpmint1,FALLING);
|
attachInterrupt(I1,rpmint1,FALLING);
|
||||||
@ -88,69 +129,42 @@ void setup() { /////////////////////////////////////////////////////////////////
|
|||||||
|
|
||||||
SAVE=0; // load/initialize settings
|
SAVE=0; // load/initialize settings
|
||||||
if (eer(0)!=SAVETAG) {
|
if (eer(0)!=SAVETAG) {
|
||||||
for (int i=0;i<2;i++) {;v[i]=300;b[i]=700;btime[i]=30;cat[i]=0;ctime[i]=120;rtime[i]=60;F[i]=0;rnval[i]=0;}
|
for (i=0;i<2;i++) {;v[i]=300;b[i]=700;btime[i]=30;cat[i]=0;ctime[i]=120;rtime[i]=60;F[i]=0;rnval[i]=0;}
|
||||||
brght=5;seed=0;
|
seed=0;
|
||||||
eew(0,SAVETAG);save();
|
eew(0,SAVETAG);save();
|
||||||
} else {
|
} else {
|
||||||
for (int i=0;i<2;i++) {
|
for (i=0;i<2;i++) {
|
||||||
v[i]=eer(1+i);b[i]=eer(3+i);btime[i]=eer(5+i);cat[i]=eer(7+i);
|
v[i]=eer(1+i);b[i]=eer(3+i);btime[i]=eer(5+i);cat[i]=eer(7+i);
|
||||||
ctime[i]=eer(9+i);F[i]=eer(11+i);rtime[i]=eer(13+i);rnval[i]=eer(15+i);
|
ctime[i]=eer(9+i);F[i]=eer(11+i);rtime[i]=eer(13+i);rnval[i]=eer(15+i);
|
||||||
}
|
}
|
||||||
seed=eer(100)+1;eew(100,seed);randomSeed(seed);
|
seed=eer(100)+1;eew(100,seed);randomSeed(seed);
|
||||||
brght=eer(101);
|
for (i=0;i<NP;i++) *P[i]=eer(200+i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clkorg=CLK;dtorg=DT;if (SWAPENC) {;DT=clkorg;CLK=dtorg;} // swap encoder direction
|
||||||
|
|
||||||
lset();
|
lset();
|
||||||
|
|
||||||
enclast=digitalRead(CLK); // get encoder state
|
enclast=digitalRead(CLK); // get encoder state
|
||||||
|
|
||||||
for (int i=0;i<2;i++) catts[i]=stop[i]=vts[i]=ots[i]=rndts[i]=MS;xts=sts=rts=swts=buts=savets=MS; // timer
|
for (i=0;i<2;i++) catts[i]=stop[i]=vts[i]=ots[i]=rndts[i]=MS;xts=sts=rts=swts=buts=savets=MS; // timer
|
||||||
updatePWM();updatelcd();updatespeed();updatemarker(); // update all
|
updatePWM();updatelcd();updatespeed();updatemarker(); // update all
|
||||||
|
|
||||||
slcd(0,0,5,VERSION); // show version
|
slcd(0,0,5,VERSION); // show version
|
||||||
|
|
||||||
|
if (FANINIT) { // setup fans
|
||||||
|
digitalWrite(R0,LOW);digitalWrite(R1,LOW);delay(3000);digitalWrite(R0,HIGH);digitalWrite(R1,HIGH);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void loop() { //////////////////////////////////////////////////////////////////////////////////////////// LOOP
|
void loop() { //////////////////////////////////////////////////////////////////////////////////////////// LOOP
|
||||||
|
|
||||||
if (Serial.available() > 0) { ////////////////////////////////////////////////////////// serial communication
|
|
||||||
int n=cutcmd(Serial.readString());
|
|
||||||
int err=1;
|
|
||||||
int i=cut(icmd[1],0,1);
|
|
||||||
if (cmd[0]=="info" && n==1) {;err=0;}
|
|
||||||
if (cmd[0]=="version" && n==1) {;SXN(VERSION);return;}
|
|
||||||
if (cmd[0]=="save" && n==1) {;save();}
|
|
||||||
if (cmd[0]=="speed" && n==3) {;v[i]=cut(icmd[2],FANMIN,FANMAX);err=0;}
|
|
||||||
if (cmd[0]=="bspeed" && n==3) {;b[i]=cut(icmd[2],FANMIN,FANMAX);err=0;}
|
|
||||||
if (cmd[0]=="btime" && n==3) {;btime[i]=cut(icmd[2],0,60);err=0;}
|
|
||||||
if (cmd[0]=="ctime" && n==3) {;ctime[i]=cut(icmd[2],60,240);err=0;}
|
|
||||||
if (cmd[0]=="rtime" && n==3) {;rtime[i]=cut(icmd[2],0,240);err=0;}
|
|
||||||
if (cmd[0]=="rnval" && n==3) {;rnval[i]=cut(icmd[2],0,1000);err=0;}
|
|
||||||
if (cmd[0]=="on" && n==2) {;fset(i,1);err=0;}
|
|
||||||
if (cmd[0]=="off" && n==2) {;fset(i,0);err=0;}
|
|
||||||
if (cmd[0]=="bon" && n==2) {;bset(i,1);err=0;}
|
|
||||||
if (cmd[0]=="boff" && n==2) {;bset(i,0);err=0;}
|
|
||||||
if (cmd[0]=="con" && n==2) {;cat[i]=1;catts[i]=MS;err=0;}
|
|
||||||
if (cmd[0]=="coff" && n==2) {;cat[i]=0;catts[i]=MS;err=0;}
|
|
||||||
if (cmd[0]=="otime" && n==3) {;oset(i,icmd[2]);err=0;}
|
|
||||||
|
|
||||||
updatelcd();
|
|
||||||
for (int i=0;i<2;i++) {
|
|
||||||
SX(F[i]);SX(":");SX((int)(v[i]));SX(":");SX((int)(b[i]));SX(":");SX(rpm[i]);SX(":");
|
|
||||||
SX(xpm[i]);SX(":");SX(r[i]);SX(":");SX(bstate[i]);SX(":");SX(btime[i]);SX(":");
|
|
||||||
SX(cat[i]);SX(":");SX(ctime[i]);SX(":");SX(rtime[i]);SX(":");SX(otime[i]);SX(":");SX(rnval[i]);SX(":");
|
|
||||||
if (bstate[i]) SX((((long)btime[i]*60000)-(MS-(long)bts[i]))/1000+1); else SX(0);SX(":");
|
|
||||||
if (ostate[i]) SX((((long)otime[i]*3600000)-(MS-(long)ots[i]))/1000+1); else SX(0);SX(":");
|
|
||||||
}
|
|
||||||
SX(VERSION);SX(":");SXN(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SAVE>0 && MS-savets>SAVEDELAY) {;save();SAVE=0;savets=MS;} ////////////////////// save settings if needed
|
if (SAVE>0 && MS-savets>SAVEDELAY) {;save();SAVE=0;savets=MS;} ////////////////////// save settings if needed
|
||||||
if (MS-savets>SAVEDELAY/5) bclr=1;
|
if (MS-savets>SAVEDELAY/5) bclr=1;
|
||||||
|
|
||||||
for (int i=0;i<2;i++) {
|
for (int i=0;i<2;i++) {
|
||||||
|
|
||||||
if (MS-rndts[i]>RNDINTERVL) { //////////////////////////////////////////////////////////////// random timer
|
if (MS-rndts[i]>((long)RNDINTERVAL*1000)) { ////////////////////////////////////////////////// random timer
|
||||||
rnd[i]=int(random(0,rnval[i]+1)/10)*10;rndts[i]=MS;updatelcd();
|
rnd[i]=int(random(0,rnval[i]+1)/10)*10;rndts[i]=MS;updatelcd();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,7 +176,7 @@ void loop() { //////////////////////////////////////////////////////////////////
|
|||||||
catts[i]=MS;cstate[i]=1;F[i]=0;stop[i]=MS;updatePWM();updatespeed();
|
catts[i]=MS;cstate[i]=1;F[i]=0;stop[i]=MS;updatePWM();updatespeed();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cstate[i] && MS-stop[i]>CATCHSTOP && F[i]==0) { ////////////////////////// stop cat fish and start over
|
if (cstate[i] && MS-stop[i]>((long)CATCHSTOP*1000) && F[i]==0) { ///////////// stop cat fish and start over
|
||||||
cstate[i]=0;F[i]=1;vts[i]=MS;rts=MS+2000;updatePWM();updatespeed();
|
cstate[i]=0;F[i]=1;vts[i]=MS;rts=MS+2000;updatePWM();updatespeed();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,12 +184,12 @@ void loop() { //////////////////////////////////////////////////////////////////
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MS-xts>SINTERVAL) { /////////////////////////////////////////////////////////////////// speed measurement
|
if (MS-xts>(SINTERVAL*100)) { ///////////////////////////////////////////////////////////// speed measurement
|
||||||
for (int i=0;i<2;i++) xpm[i]=xpm[i]*(SAVERAGE-1)/SAVERAGE+(bc[i]/((MS-xts)/1000.0)*30.0)/SAVERAGE;
|
for (int i=0;i<2;i++) xpm[i]=xpm[i]*(SAVERAGE-1)/SAVERAGE+(bc[i]/((MS-xts)/1000.0)*30.0)/SAVERAGE;
|
||||||
updatespeed();xts=MS;bc[0]=0;bc[1]=0;
|
updatespeed();xts=MS;bc[0]=0;bc[1]=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MS-rts>RINTERVAL) { //////////////////////////////////////////////////////////////////// speed regulation
|
if (MS-rts>(RINTERVAL*100)) { ////////////////////////////////////////////////////////////// speed regulation
|
||||||
for (int i=0;i<2;i++) {
|
for (int i=0;i<2;i++) {
|
||||||
rpm[i]=ac[i]/((MS-sts)/1000.0)*30.0;
|
rpm[i]=ac[i]/((MS-sts)/1000.0)*30.0;
|
||||||
ac[i]=0;
|
ac[i]=0;
|
||||||
@ -195,7 +209,7 @@ void loop() { //////////////////////////////////////////////////////////////////
|
|||||||
bdelay=0; //////////////////////////////////////////////////////////////////////////////////// process switch
|
bdelay=0; //////////////////////////////////////////////////////////////////////////////////// process switch
|
||||||
if (!bprocess) {
|
if (!bprocess) {
|
||||||
while (!digitalRead(SW)){
|
while (!digitalRead(SW)){
|
||||||
bdelay++;delay(25);bprocess=1;if (bdelay>20) break;
|
bdelay++;delay(15);bprocess=1;if (bdelay>20) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,12 +228,20 @@ void loop() { //////////////////////////////////////////////////////////////////
|
|||||||
if (bstate[M]==0) bset(M,1); else {;bset(M,0);if (BOFF) fset(M,0);}
|
if (bstate[M]==0) bset(M,1); else {;bset(M,0);if (BOFF) fset(M,0);}
|
||||||
bclr=1;
|
bclr=1;
|
||||||
}
|
}
|
||||||
|
if (S==8 && !LOCK) { // exit config mode
|
||||||
|
M=2;save();updatemarker();
|
||||||
|
if (SWAPENC) {;DT=clkorg;CLK=dtorg;}
|
||||||
|
else {;DT=dtorg;CLK=clkorg;}
|
||||||
|
if (RESET==1) {;RESET=0;eew(0,0);save();resetFunc();}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
save();updatespeed();bdelay=0;
|
save();updatespeed();bdelay=0;
|
||||||
|
|
||||||
} else if (bdelay>0 && bdelay<20 && !LOCK) { // short button press, switch: menu -> fan 0 -> fan 1
|
} else if (bdelay>0 && bdelay<20 && !LOCK) { // short button press, switch: menu -> fan 0 -> fan 1
|
||||||
M++;if (S==8 && M==1) M=2;if (M>2) M=0;
|
M++;
|
||||||
|
if (S==8 && M==2) M=0;
|
||||||
|
if (M>2) M=0;
|
||||||
updatemarker();
|
updatemarker();
|
||||||
bdelay=0;
|
bdelay=0;
|
||||||
}
|
}
|
||||||
@ -233,49 +255,55 @@ void loop() { //////////////////////////////////////////////////////////////////
|
|||||||
if(!encval){
|
if(!encval){
|
||||||
|
|
||||||
if (digitalRead(DT) != encval) { // turn encoder clockwise
|
if (digitalRead(DT) != encval) { // turn encoder clockwise
|
||||||
if (M==2) S++; // scroll menu
|
if (M==2) S++; // scroll menu
|
||||||
else {
|
else {
|
||||||
if (S==0) v[M]+=SPEEDINC; // fan speed up
|
if (S==0) v[M]=speedinc(v[M],1); // fan speed up
|
||||||
if (S==1) b[M]+=SPEEDINC; // boost speed up
|
if (S==1) b[M]=speedinc(b[M],1); // boost speed up
|
||||||
if (S==2) btime[M]+=BINC; // boost time up
|
if (S==2) btime[M]+=BINC; // boost time up
|
||||||
if (S==3) cat[M]++; // cat on/off
|
if (S==3) cat[M]++; // cat on/off
|
||||||
if (S==4) ctime[M]+=CINC; // cat time up
|
if (S==4) ctime[M]+=CINC; // cat time up
|
||||||
if (S==5) rtime[M]+=RINC; // rise time up
|
if (S==5) rtime[M]+=RINC; // rise time up
|
||||||
if (S==6) otime[M]+=OINC; // off time up
|
if (S==6) otime[M]+=OINC; // off time up
|
||||||
if (S==7) rnval[M]+=SPEEDINC; // random value
|
if (S==7) rnval[M]+=RNDINC; // random value
|
||||||
if (S==8) brght++; // increase LCD brightness
|
if (S==8 && M==0) C++; // increase config menu
|
||||||
|
|
||||||
|
if (S==8 && M==1) *P[C]=cut(*P[C]+Cinc[C],Cmin[C],Cmax[C]); // increase configuration value
|
||||||
}
|
}
|
||||||
} else { // turn encoder counterclockwise
|
} else { // turn encoder counterclockwise
|
||||||
if (M==2) S--; // scroll menu
|
if (M==2) S--; // scroll menu
|
||||||
else {
|
else {
|
||||||
if (S==0) v[M]-=SPEEDINC; // fan speed down
|
if (S==0) v[M]=speedinc(v[M],0); // fan speed down
|
||||||
if (S==1) b[M]-=SPEEDINC; // boost speed down
|
if (S==1) b[M]=speedinc(b[M],0); // boost speed down
|
||||||
if (S==2) btime[M]-=BINC; // boost time down
|
if (S==2) btime[M]-=BINC; // boost time down
|
||||||
if (S==3) cat[M]--; // cat on/off
|
if (S==3) cat[M]--; // cat on/off
|
||||||
if (S==4) ctime[M]-=CINC; // cat time down
|
if (S==4) ctime[M]-=CINC; // cat time down
|
||||||
if (S==5) rtime[M]-=RINC; // rise time down
|
if (S==5) rtime[M]-=RINC; // rise time down
|
||||||
if (S==6) otime[M]-=OINC; // off time down
|
if (S==6) otime[M]-=OINC; // off time down
|
||||||
if (S==7) rnval[M]-=SPEEDINC; // random value
|
if (S==7) rnval[M]-=RNDINC; // random value
|
||||||
if (S==8) brght--; // decrease LCD brightness
|
if (S==8 && M==0) C--; // decrease config menu
|
||||||
|
|
||||||
|
if (S==8 && M==1) *P[C]=cut(*P[C]-Cinc[C],Cmin[C],Cmax[C]); // decrease configuration value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i=0;i<2;i++) if (b[i]<v[i]) b[i]=v[i];
|
for (int i=0;i<2;i++) if (b[i]<v[i]) b[i]=v[i];
|
||||||
|
|
||||||
if (M!=2) {
|
if (M!=2) {
|
||||||
if (S<=1) {;updatePWM();rts=MS+RDELAY;} // apply (boost) speed change
|
if (S<=1) {;updatePWM();rts=MS+(RDELAY*100);} // apply (boost) speed change
|
||||||
if (S==2) btime[M]=cut(btime[M],0,99); // check boost time
|
if (S==2) btime[M]=cut(btime[M],0,99); // check boost time
|
||||||
if (S==3) {;cat[M]=cut(cat[M],0,1);catts[M]=MS;} // check cat
|
if (S==3) {;cat[M]=cut(cat[M],0,1);catts[M]=MS;} // check cat
|
||||||
if (S==4) ctime[M]=cut(ctime[M],60,240); // check cat time
|
if (S==4) ctime[M]=cut(ctime[M],60,240); // check cat time
|
||||||
if (S==5) rtime[M]=cut(rtime[M],0,240); // check rise time
|
if (S==5) rtime[M]=cut(rtime[M],0,240); // check rise time
|
||||||
if (S==6) oset(M,otime[M]); // check off time
|
if (S==6) oset(M,otime[M]); // check off time
|
||||||
if (S==7) {;rnval[M]=cut(rnval[M],0,1000);updatePWM();} // apply random value change
|
if (S==7) {;rnval[M]=cut(rnval[M],0,1000);updatePWM();} // apply random value change
|
||||||
if (S==8) lset(); // set LCD brightness
|
if (S==8 && C==0) lset(); // set LCD brightness
|
||||||
}
|
}
|
||||||
|
|
||||||
|
C=cut(C,0,NP-1); // check configuration mode
|
||||||
|
|
||||||
if (M==2) S=cut(S,0,8); // check menu mode
|
if (M==2) S=cut(S,0,8); // check menu mode
|
||||||
|
|
||||||
SAVE++;updatelcd();delay(50);
|
SAVE++;updatelcd();delay(25);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
enclast=encval;
|
enclast=encval;
|
||||||
@ -284,9 +312,27 @@ void loop() { //////////////////////////////////////////////////////////////////
|
|||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////// SUPPORT
|
/////////////////////////////////////////////////////////////////////////////////////////////////////// SUPPORT
|
||||||
|
|
||||||
|
void defcon(int n, int inc, int min, int max) { ///////////////////////////////////////////// set config limits
|
||||||
|
Cinc[n]=inc; Cmin[n]=min; Cmax[n]=max;
|
||||||
|
}
|
||||||
|
|
||||||
|
int speedinc(int s,int mode) { ////////////////////////////////////////////////////// calculate speed increment
|
||||||
|
if (mode==0) {
|
||||||
|
if (s<=SPEEDSTEP1) return s-SPEEDINC1;
|
||||||
|
if (s<=SPEEDSTEP2) return s-SPEEDINC2;
|
||||||
|
return s-SPEEDINC3;
|
||||||
|
}
|
||||||
|
if (mode==1) {
|
||||||
|
if (s<SPEEDSTEP1) return s+SPEEDINC1;
|
||||||
|
if (s<SPEEDSTEP2) return s+SPEEDINC2;
|
||||||
|
return s+SPEEDINC3;
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
void lset() { ////////////////////////////////////////////////////////////////////////////// set LCD brightness
|
void lset() { ////////////////////////////////////////////////////////////////////////////// set LCD brightness
|
||||||
brght=cut(brght,0,9);
|
LGHT=cut(LGHT,0,9);
|
||||||
analogWrite(PWM2,LCDB[brght]);
|
analogWrite(PWM2,LCDB[LGHT]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void oset(int n,int t) { ///////////////////////////////////////////////////////////////// set switch off timer
|
void oset(int n,int t) { ///////////////////////////////////////////////////////////////// set switch off timer
|
||||||
@ -296,7 +342,7 @@ void oset(int n,int t) { ///////////////////////////////////////////////////////
|
|||||||
|
|
||||||
void fset(int n,int s) { /////////////////////////////////////////////////////////////// set fan state (on/off)
|
void fset(int n,int s) { /////////////////////////////////////////////////////////////// set fan state (on/off)
|
||||||
if (s==1) {
|
if (s==1) {
|
||||||
rts=MS+RDELAY;F[n]=1;catts[n]=vts[n]=MS;r[n]=0;
|
rts=MS+(RDELAY*100);F[n]=1;catts[n]=vts[n]=MS;r[n]=0;
|
||||||
} else {
|
} else {
|
||||||
F[n]=0;bstate[n]=0;
|
F[n]=0;bstate[n]=0;
|
||||||
}
|
}
|
||||||
@ -306,41 +352,42 @@ void fset(int n,int s) { ///////////////////////////////////////////////////////
|
|||||||
|
|
||||||
void bset(int n,int s) { ///////////////////////////////////////////////////////////// set boost state (on/off)
|
void bset(int n,int s) { ///////////////////////////////////////////////////////////// set boost state (on/off)
|
||||||
if (s==1) {
|
if (s==1) {
|
||||||
rts=MS+RDELAY;bstate[n]=1;bts[n]=MS;F[n]=1;vts[n]=MS;
|
rts=MS+(RDELAY*100);bstate[n]=1;bts[n]=MS;F[n]=1;vts[n]=MS;
|
||||||
} else {
|
} else {
|
||||||
bstate[n]=0;rts=MS+RDELAY;
|
bstate[n]=0;rts=MS+(RDELAY*100);
|
||||||
}
|
}
|
||||||
updatePWM();
|
updatePWM();
|
||||||
SAVE++;
|
SAVE++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void updatelcd() { ///////////////////////////////////////////////////////////////////////////////// update LCD
|
void updatelcd() { ///////////////////////////////////////////////////////////////////////////////// update LCD
|
||||||
|
|
||||||
for (int i=0;i<2;i++) {
|
for (int i=0;i<2;i++) {
|
||||||
if (S==0) {;slcd(1,1,5,"SPEED");ilcd(7+i*5,1,-4,v[i]);}
|
if (S==0) {;slcd(1,1,5,F("SPEED"));ilcd(7+i*5,1,-4,v[i]);}
|
||||||
if (S==1) {;slcd(1,1,5,"BOOST");ilcd(7+i*5,1,-4,int(b[i]));}
|
if (S==1) {;slcd(1,1,5,F("BOOST"));ilcd(7+i*5,1,-4,int(b[i]));}
|
||||||
if (S==2) {;slcd(1,1,5,"BTIME");ilcd(7+i*5,1,-4,int(btime[i]));}
|
if (S==2) {;slcd(1,1,5,F("BTIME"));ilcd(7+i*5,1,-4,int(btime[i]));}
|
||||||
if (S==3) {
|
if (S==3) {
|
||||||
slcd(1,1,5,"CATCH");
|
slcd(1,1,5,F("CATCH"));
|
||||||
if (cat[i]==0) slcd( 7+i*5,1,-4,"OFF"); else slcd( 7+i*5,1,-3,"ON");
|
if (cat[i]==0) slcd( 7+i*5,1,-4,F("OFF")); else slcd( 7+i*5,1,-3,F("ON"));
|
||||||
}
|
}
|
||||||
if (S==4) {;slcd(1,1,5,"CTIME");ilcd(7+i*5,1,-4,int(ctime[i]));}
|
if (S==4) {;slcd(1,1,5,F("CTIME"));ilcd(7+i*5,1,-4,int(ctime[i]));}
|
||||||
if (S==5) {;slcd(1,1,5,"RTIME");ilcd(7+i*5,1,-4,int(rtime[i]));}
|
if (S==5) {;slcd(1,1,5,F("RTIME"));ilcd(7+i*5,1,-4,int(rtime[i]));}
|
||||||
if (S==6) {;slcd(1,1,5,"OTIME");ilcd(7+i*5,1,-4,int(otime[i]));}
|
if (S==6) {;slcd(1,1,5,F("OTIME"));ilcd(7+i*5,1,-4,int(otime[i]));}
|
||||||
if (S==7) {;slcd(1,1,5,"RNVAL");ilcd(7+i*5,1,-4,int(rnval[i]));}
|
if (S==7) {;slcd(1,1,5,F("RNVAL"));ilcd(7+i*5,1,-4,int(rnval[i]));}
|
||||||
}
|
}
|
||||||
if (S==8) {;slcd(1,1,5,"BRGHT");ilcd(7,1,-4,brght);slcd(7+5,1,-4," ");}
|
if (S==8) {;slcd(1,1,-5,F("CFG"));slcd(7,1,-4,CF[C]);ilcd(7+5,1,-4,*P[C]);}
|
||||||
}
|
}
|
||||||
|
|
||||||
void updatemarker() { ////////////////////////////////////////////////////////////////////// update menu marker
|
void updatemarker() { ////////////////////////////////////////////////////////////////////// update menu marker
|
||||||
slcd(0,1,1," ");slcd(6,1,1," ");slcd(11,1,1," ");
|
slcd(0,1,1,F(" "));slcd(6,1,1,F(" "));slcd(11,1,1,F(" "));
|
||||||
int m[]={6,11,0};if (!LOCK) clcd(m[M],1,0);
|
int m[]={6,11,0};if (!LOCK) clcd(m[M],1,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void updatespeed() { ///////////////////////////////////////////////////////////////////////// update fan speed
|
void updatespeed() { ///////////////////////////////////////////////////////////////////////// update fan speed
|
||||||
if (bclr) slcd(0,0,6," ");
|
if (bclr) slcd(0,0,6,F(" "));
|
||||||
for (int i=0;i<2;i++) {
|
for (int i=0;i<2;i++) {
|
||||||
slcd(6+i*5,0,1," ");
|
slcd(6+i*5,0,1," ");
|
||||||
if (cstate[i]) slcd(7+i*5,0,-4,"CAT");
|
if (cstate[i]) slcd(7+i*5,0,-4,F("CAT"));
|
||||||
else {
|
else {
|
||||||
if (F[i]) {
|
if (F[i]) {
|
||||||
if (bstate[i]) ilcd(1+i*3,0,-2, (((long)btime[i]*60000)-(MS-(long)bts[i]))/1000/60+1);
|
if (bstate[i]) ilcd(1+i*3,0,-2, (((long)btime[i]*60000)-(MS-(long)bts[i]))/1000/60+1);
|
||||||
@ -350,7 +397,7 @@ void updatespeed() { ///////////////////////////////////////////////////////////
|
|||||||
else {
|
else {
|
||||||
if (xv[i]>=v[i] && rnval[i]>0 && !bstate[i]) clcd(6+i*5,0,2);
|
if (xv[i]>=v[i] && rnval[i]>0 && !bstate[i]) clcd(6+i*5,0,2);
|
||||||
}
|
}
|
||||||
} else slcd(7+i*5,0,-4,"OFF");
|
} else slcd(7+i*5,0,-4,F("OFF"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -368,22 +415,17 @@ void slcd(int x,int y, int l,String s) { ///////////////////////////////////////
|
|||||||
}
|
}
|
||||||
|
|
||||||
void calcramp(int i) { ///////////////////////////////////////////////////////////// calculate speed ramp value
|
void calcramp(int i) { ///////////////////////////////////////////////////////////// calculate speed ramp value
|
||||||
xb[i]=b[i];if (bstate[i]) xb[i]=cut(((b[i]-v[i])/(rtime[i]*1000.0)*(MS-bts[i]))+v[i],v[i],b[i]);
|
xb[i]=b[i];
|
||||||
xv[i]=v[i];xv[i]=cut(((v[i]-FANMIN)/(rtime[i]*1000.0)*(MS-vts[i]))+FANMIN,FANMIN,v[i]);
|
int rt=rtime[i]?rtime[i]:1;
|
||||||
|
if (bstate[i]) xb[i]=cut(((b[i]-v[i])/(rt*1000.0)*(MS-bts[i]))+v[i],v[i],b[i]);
|
||||||
|
xv[i]=v[i];
|
||||||
|
xv[i]=cut(((v[i]-FANMIN)/(rt*1000.0)*(MS-vts[i]))+FANMIN,FANMIN,v[i]);
|
||||||
if (rnval[i]>0 && xv[i]>=v[i]) xv[i]=cut(xv[i]+rnd[i],FANMIN,FANMAX);
|
if (rnval[i]>0 && xv[i]>=v[i]) xv[i]=cut(xv[i]+rnd[i],FANMIN,FANMAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setPWM(int n,int v) { /////////////////////////////////////////// set value to OCR1x and states to off pin
|
void setPWM(int n,int v) { /////////////////////////////////////////// set value to OCR1x and states to off pin
|
||||||
if (n==0) {
|
if (n==0) OCR1A=v;
|
||||||
OCR1A=v;
|
if (n==1) OCR1B=v;
|
||||||
if (v==0) digitalWrite(OFF0,OFFSTATE?HIGH:LOW);
|
|
||||||
else digitalWrite(OFF0,OFFSTATE?LOW:HIGH);
|
|
||||||
}
|
|
||||||
if (n==1) {
|
|
||||||
OCR1B=v;
|
|
||||||
if (v==0) digitalWrite(OFF1,OFFSTATE?HIGH:LOW);
|
|
||||||
else digitalWrite(OFF1,OFFSTATE?LOW:HIGH);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void updatePWM() { ////////////////////////////////////////////////////////////// update PWM output (fan speed)
|
void updatePWM() { ////////////////////////////////////////////////////////////// update PWM output (fan speed)
|
||||||
@ -391,8 +433,14 @@ void updatePWM() { /////////////////////////////////////////////////////////////
|
|||||||
v[i]=cut(v[i],FANMIN,FANMAX);
|
v[i]=cut(v[i],FANMIN,FANMAX);
|
||||||
b[i]=cut(b[i],FANMIN,FANMAX);
|
b[i]=cut(b[i],FANMIN,FANMAX);
|
||||||
calcramp(i);
|
calcramp(i);
|
||||||
if (!F[i]) setPWM(i,0); else setPWM(i,cut((bstate[i]?xb[i]:xv[i])/(FANMAX/320.0)+r[i],0,320));
|
if (!F[i]) setPWM(i,0); else setPWM(i,cut((bstate[i]?xb[i]:xv[i])/(FANMAX/320.0)+r[i],1,320));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((bstate[0]?b[0]:v[0])>=RTHRES) digitalWrite(R0,LOW);
|
||||||
|
else digitalWrite(R0,HIGH);
|
||||||
|
|
||||||
|
if ((bstate[1]?b[1]:v[1])>=RTHRES) digitalWrite(R1,LOW);
|
||||||
|
else digitalWrite(R1,HIGH);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpmint0() {;ac[0]++;bc[0]++;} ///////////////////////////////////////////////////////////// rpm interrupts
|
void rpmint0() {;ac[0]++;bc[0]++;} ///////////////////////////////////////////////////////////// rpm interrupts
|
||||||
@ -410,16 +458,7 @@ void save() { //////////////////////////////////////////////////////////////////
|
|||||||
eew(9+i,ctime[i]);eew(11+i,F[i]);eew(13+i,rtime[i]);eew(15+i,rnval[i]);
|
eew(9+i,ctime[i]);eew(11+i,F[i]);eew(13+i,rtime[i]);eew(15+i,rnval[i]);
|
||||||
}
|
}
|
||||||
eew(100,seed);
|
eew(100,seed);
|
||||||
eew(101,brght);
|
for (int i=0;i<NP;i++) eew(200+i,*P[i]);
|
||||||
}
|
|
||||||
|
|
||||||
int cutcmd(String data) { ///////////////////////////////////////////////////////////// get saperated substring
|
|
||||||
int mi=data.length(),n=0,j=0;
|
|
||||||
for (int i=0;i<=mi;i++) {
|
|
||||||
if (data.charAt(i) == ':' || i == mi) {;cmd[n]=data.substring(j,i);j=i+1;n++;}
|
|
||||||
}
|
|
||||||
for (int i=1;i<n;i++) icmd[i]=cmd[i].toInt();
|
|
||||||
return n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////// END
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////// END
|
||||||
|
61
stirctl
@ -1,61 +0,0 @@
|
|||||||
#!/usr/bin/perl
|
|
||||||
###################################################################################### stir controll (mwx'2019)
|
|
||||||
use Device::SerialPort;
|
|
||||||
use Time::HiRes qw( usleep );
|
|
||||||
|
|
||||||
$dev='/dev/ttyACM0';
|
|
||||||
|
|
||||||
my $port = Device::SerialPort->new($dev); ################################################### setup serial port
|
|
||||||
|
|
||||||
$port->baudrate(9600);
|
|
||||||
$port->databits(8);
|
|
||||||
$port->parity("none");
|
|
||||||
$port->stopbits(1);
|
|
||||||
|
|
||||||
$port->lookfor();
|
|
||||||
|
|
||||||
$cmd=join(':',@ARGV);$cmd='info' if ($cmd=~/^\s*$/);
|
|
||||||
|
|
||||||
@r=split(':',&scmd($cmd));
|
|
||||||
|
|
||||||
print " Left Right\n";
|
|
||||||
printf("Stirrer On: %6d %6d\n", $r[0],$r[15]);
|
|
||||||
printf("Speed: %6d %6d\n", $r[1],$r[16]);
|
|
||||||
printf("Boost Speed: %6d %6d\n", $r[2],$r[17]);
|
|
||||||
printf("RPM: %6d %6d\n", $r[3],$r[18]);
|
|
||||||
printf("Average RPM: %6d %6d\n", $r[4],$r[19]);
|
|
||||||
printf("Regulation: %6d %6d\n", $r[5],$r[20]);
|
|
||||||
printf("Boost On: %6d %6d\n", $r[6],$r[21]);
|
|
||||||
printf("Boost Time: %6d %6d\n", $r[7],$r[22]);
|
|
||||||
printf("Catch On: %6d %6d\n", $r[8],$r[23]);
|
|
||||||
printf("Catch Time: %6d %6d\n", $r[9],$r[24]);
|
|
||||||
printf("Rise Time: %6d %6d\n", $r[10],$r[25]);
|
|
||||||
printf("Off Time: %6d %6d\n", $r[11],$r[26]);
|
|
||||||
printf("Random Value: %6d %6d\n", $r[12],$r[27]);
|
|
||||||
printf("Boost Remain: %6d %6d\n", $r[13],$r[28]);
|
|
||||||
printf("Off Remain: %6d %6d\n", $r[14],$r[29]);
|
|
||||||
printf("Error: %d\nVersion: %s\n", $r[30],$r[31]);
|
|
||||||
|
|
||||||
|
|
||||||
sub scmd() { ##################################################################################### send command
|
|
||||||
my($cmd,$quiet)=@_;
|
|
||||||
|
|
||||||
$port->write($cmd);
|
|
||||||
my $founddata=0;
|
|
||||||
$msg="";
|
|
||||||
for ($i=0;$i<1000;$i++) {
|
|
||||||
|
|
||||||
$in = $port->lookfor();
|
|
||||||
$founddata=1 if ($in ne "");
|
|
||||||
$msg.=$in;
|
|
||||||
|
|
||||||
last if ($in eq "" && $founddata);
|
|
||||||
|
|
||||||
&usleep(2500);
|
|
||||||
}
|
|
||||||
|
|
||||||
$msg=~s/[\r\n]+//g;
|
|
||||||
return $msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
########################################################################################################### END
|
|
@ -1,13 +0,0 @@
|
|||||||
# Stir Shield
|
|
||||||
|
|
||||||
Stir shield for Arduino UNO from Adrian Sigel.
|
|
||||||
|
|
||||||
<p align="center">
|
|
||||||
<img src="https://github.com/micworg/stir/blob/master/unoshield/images/pcb_top.png" width=500>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p align="center">
|
|
||||||
<img src="https://github.com/micworg/stir/blob/master/unoshield/images/pcb_bottom.png" width=500>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|