Compare commits

...

36 Commits

Author SHA1 Message Date
15af0c7e9a Update README.md 2024-10-18 14:06:19 +02:00
2bb280c208 Update README.md 2024-10-18 14:04:14 +02:00
micworg
6218a4a4c7
Merge pull request #1 from BernhardSchlegel/patch-1
added links for components
2020-03-12 18:38:26 +01:00
Bernhard Schlegel
370b284bb6
added links for components 2020-03-12 18:34:34 +01:00
Michael Wesemann
8da220cbdb bug fix 2019-11-05 14:49:48 +01:00
Michael Wesemann
97aacae7b9 - 2019-10-09 11:40:47 +02:00
Michael Wesemann
052c350dad - 2019-10-09 11:37:20 +02:00
Michael Wesemann
d11fda9a71 - 2019-10-09 09:17:38 +02:00
Michael Wesemann
51b7789311 - 2019-10-09 08:52:09 +02:00
Michael Wesemann
458dfd2621 - 2019-10-09 08:49:53 +02:00
Michael Wesemann
30578560cc - 2019-10-09 08:47:24 +02:00
Michael Wesemann
96f890588d - 2019-10-09 08:46:17 +02:00
Michael Wesemann
7594f5396e - 2019-10-09 08:45:18 +02:00
Michael Wesemann
789c5f230f - 2019-10-09 08:43:26 +02:00
Michael Wesemann
e5b5a36a06 - 2019-10-09 08:42:51 +02:00
Michael Wesemann
8a2ef9be32 - 2019-10-09 08:42:30 +02:00
Michael Wesemann
cc60e10a33 - 2019-10-09 08:41:24 +02:00
Michael Wesemann
c8da085c22 - 2019-10-09 08:39:07 +02:00
Michael Wesemann
6422fa3a8a - 2019-10-09 08:38:41 +02:00
Michael Wesemann
d815054215 - 2019-10-09 08:36:53 +02:00
Michael Wesemann
4de79a9d6c - 2019-10-08 14:40:25 +02:00
Michael Wesemann
f00cb821e3 - 2019-10-08 14:39:55 +02:00
Michael Wesemann
f508e869ed - 2019-10-08 14:38:49 +02:00
Michael Wesemann
485fa38021 - 2019-10-08 14:25:08 +02:00
Michael Wesemann
0689ea7e9e - 2019-10-08 14:22:27 +02:00
Michael Wesemann
17062e17cc - 2019-10-08 14:21:09 +02:00
Michael Wesemann
c1e12c7286 - 2019-10-08 14:18:23 +02:00
Michael Wesemann
4be02dca3f - 2019-10-08 14:18:06 +02:00
Michael Wesemann
7a265978f1 - 2019-10-08 14:17:10 +02:00
Michael Wesemann
15da3e7dc8 - 2019-10-06 19:51:14 +02:00
Michael Wesemann
17aa9f611e - 2019-10-06 19:50:34 +02:00
Michael Wesemann
f5e0bcc72b - 2019-10-06 19:46:24 +02:00
Michael Wesemann
a19d1dfe54 - 2019-10-05 15:33:36 +02:00
Michael Wesemann
4feb32a702 - 2019-10-05 15:32:54 +02:00
Michael Wesemann
76f390897f - 2019-10-04 22:19:19 +02:00
Michael Wesemann
b5c6b0741d - 2019-10-04 17:45:22 +02:00
4 changed files with 218 additions and 115 deletions

View File

@ -1,11 +1,12 @@
# Dual magnetic stir controller # Dual magnetic stir controller V2
## Overview ## Overview
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. 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+pcb.jpg" width=700> <img src="https://git.fhi.mpg.de/mike/stir/raw/branch/master/images/stir+pcb.jpg" width=700>
</p> </p>
V2 supports dual voltage for the fans which increases the speed range. V2 supports dual voltage for the fans which increases the speed range.
@ -14,26 +15,32 @@ In order to put the stirrer into operation you have to change the settings in st
The stir V2 software is compatible with V1 hardware if you have used neither the RS232 Api nor the OFF0 and OFF1 relais pins. 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 ## Part List
* 1x PCB "Stir V2.0" * 1x PCB "Stir V2.0"
* 1x Arduino Nano V3 * 1x Arduino Nano V3
* 1x Voltage regulator TE818 5-24V to 5V 3A step down buck converter * 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 printrelais 5 V/DC 5A * 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 * 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 * 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 * 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 * 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 * 2x Fan BeQuiet SilentWings 3 120mm PWM Highspeed or Noctua NF-R8 Redux-1800 80mm PWM
* 1x Power supply 12V-20V DC / 2A * 1x Power supply 12V-16V DC / 2A
* 1x Built-in socket for plug-in power supply unit * 1x Built-in socket for plug-in power supply unit
* 1x I2C 16x2 Arduino LCD Display Module * 1x I2C 16x2 Arduino LCD Display Module
* 1x Rotary encoder KY-040 * 1x [Rotary encoder KY-040](https://www.conrad.de/de/p/joy-it-kodierter-drehschalter-rotary-encoder-1695709.html)
* 2x Magnet mount (3D printed) * 2x Magnet mount (3D printed)
* 4x Neodymium magnet 20x10 mm (N52, 1 oder 2 mm dick) * 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. 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>
## Reference ## Reference
This project was created based on an idea from the german 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.
@ -49,6 +56,7 @@ Special thanks for development and testing:
* Jens Warkentin * Jens Warkentin
* Bastian Werner * 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:
@ -66,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:
@ -77,30 +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)|
|`R0`, `R0`|voltage select relais pin| |`OINC` |`OINC`|off timer increment (hour)|
|`RTHRES`|voltage switch threshold (rpm)| |`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 range 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|

View File

@ -1,4 +1,4 @@
# Dual magnetic stir controller # Dual magnetic stir controller V1
## Overview ## Overview

BIN
images/v2_board.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 412 KiB

220
stir.ino
View File

@ -3,25 +3,32 @@
#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 = "2.0.1"; 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 = 2500; // 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
@ -30,7 +37,9 @@ int PWM2 = 11;
int I0 = 0; // 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 = 1; // 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
@ -38,18 +47,22 @@ int R0 = 7;
int R1 = 8; // voltage select relais 1 int R1 = 8; // voltage select relais 1
int RTHRES = 700; // voltage switch threshold (rpm) 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 RNDINTERVAL = 300000; // randon value range change interval (ms) int RNDINTERVAL = 300; // randon value range change interval (sec)
long SINTERVAL = 2000; // speed measurement internval (ms) int SINTERVAL = 20; // speed measurement internval (ds)
int SAVERAGE = 4; // speed measurement average int SAVERAGE = 4; // speed measurement average
int SAVETAG = 2001; // 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
@ -61,16 +74,45 @@ LiquidCrystal_I2C lcd(0x27,16,2); // L
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 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
@ -87,28 +129,33 @@ 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
@ -117,7 +164,7 @@ void loop() { //////////////////////////////////////////////////////////////////
for (int i=0;i<2;i++) { for (int i=0;i<2;i++) {
if (MS-rndts[i]>RNDINTERVAL) { /////////////////////////////////////////////////////////////// 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();
} }
@ -129,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();
} }
@ -137,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;
@ -181,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;
} }
@ -200,46 +255,52 @@ 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(25); SAVE++;updatelcd();delay(25);
@ -251,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
@ -263,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;
} }
@ -273,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);
@ -317,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"));
} }
} }
} }
@ -356,10 +436,10 @@ void updatePWM() { /////////////////////////////////////////////////////////////
if (!F[i]) setPWM(i,0); else setPWM(i,cut((bstate[i]?xb[i]:xv[i])/(FANMAX/320.0)+r[i],1,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 (v[0]>=RTHRES) digitalWrite(R0,LOW); if ((bstate[0]?b[0]:v[0])>=RTHRES) digitalWrite(R0,LOW);
else digitalWrite(R0,HIGH); else digitalWrite(R0,HIGH);
if (v[1]>=RTHRES) digitalWrite(R1,LOW); if ((bstate[1]?b[1]:v[1])>=RTHRES) digitalWrite(R1,LOW);
else digitalWrite(R1,HIGH); else digitalWrite(R1,HIGH);
} }
@ -378,7 +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]);
} }
/////////////////////////////////////////////////////////////////////////////////////////////////////////// END /////////////////////////////////////////////////////////////////////////////////////////////////////////// END