Compare commits

..

No commits in common. "master" and "v2.1.0" have entirely different histories.

2 changed files with 96 additions and 122 deletions

View File

@ -1,12 +1,11 @@
# Dual magnetic stir controller V2 # 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://git.fhi.mpg.de/mike/stir/raw/branch/master/images/stir+pcb.jpg" width=700> <img src="https://github.com/micworg/stir/blob/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.
@ -15,32 +14,30 @@ 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](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) * 1x Voltage regulator TE818 5-24V to 5V 3A step down buck converter
* 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 Relais Omron G5Q-1-EU 5DC switching printrelais 5 V/DC 5A
* 2x [Diode 1N4148 Diotec](https://www.conrad.de/de/p/stmicroelectronics-schottky-diode-gleichrichter-1n5822-do-201ad-40-v-einzeln-168275.html) * 2x Diode 1N4148 Diotec
* 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) * 1x Electrolytic capacitor 1000µF/16V Yageo SE016M1000B5S-1015
* 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) * 2x Diode 1N5822 STMicroelectronics Schottky-Diode
* 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) * 4x Metal film resistor 10 KOhm 0,6 W
* 2x Fan BeQuiet SilentWings 3 120mm PWM Highspeed or Noctua NF-R8 Redux-1800 80mm PWM * 2x Fan BeQuiet SilentWings 3 120mm PWM Highspeed or Noctua NF-R8 Redux-1800 80mm PWM
* 1x Power supply 12V-16V 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](https://www.conrad.de/de/p/joy-it-kodierter-drehschalter-rotary-encoder-1695709.html) * 1x Rotary encoder KY-040
* 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"> <p align="center">
<img src="https://git.fhi.mpg.de/mike/stir/raw/branch/master/images/v2_board.jpg" width=350> <img src="https://github.com/micworg/stir/blob/master/images/v2_board.jpg" width=350>
</p> </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.
@ -56,7 +53,6 @@ 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:
@ -76,12 +72,6 @@ All functions are controlled by the KY-040 encoder:
* **Other menu options**: * **Other menu options**:
* **CFG**: Configuration menu * **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:
* **Bottom Left**: Menu * **Bottom Left**: Menu
@ -91,39 +81,35 @@ Functions in the congirutation sub menu
## Settings (in stir.ino) ## Settings (in stir.ino)
|Value|Config|Description| |Value|Config Menu Name|Description|
|:----------------|:-----|:----------| |:----|:---------------|:----------|
|`LGHT` |`LGHT`|LCD display brightness| |`LGHT`|`LGHT`|LCD display brightness|
|`SPEEDINC1` |`SPI1`|increment of speed values when turning the encoder (1. range)| |`SPEEDINC1`, `SPEEDINC2`, `SPEEDINC3`|`SPI1`, `SPI2`, `SPI3`|increment of speed values when turning the encoder|
|`SPEEDINC2` |`SPI2`|increment of speed values when turning the encoder (2. range)| |`SPEEDSTEP1`, `SPEEDSTEP2`|`SPS1`, `SPS2`|speed increment steps (increment changes at these values)|
|`SPEEDINC3` |`SPI3`|increment of speed values when turning the encoder (3. range)| |`FANMIN`|`FMIN`|fan minimum speed (should be a value at which the fan runs safely) (rpm)|
|`SPEEDSTEP1` |`SPS1`|speed increment steps (increment changes at these values, separates range 1 and 2)| |`FANMAX`|`FMAX`|maximum speed of the fan (it is important that this is the real maximum value of the fan) (rpm)|
|`SPEEDSTEP2` |`SPS2`|speed increment steps (increment changes at these values, separates range 2 and 3))| |`FANINIT`|`FINI`|set fan to hight voltage at boot (3 sec)|
|`FANMIN` |`FMIN`|fan minimum speed (should be a value at which the fan runs safely) (rpm)| |`BOFF`|`BOFF`|if set boost off will also turn the normal mode off|
|`FANMAX` |`FMAX`|fan maximum speed (it's important that this is the real maximum value of the fan) (rpm)| |`BINC`|`BINC`|boost time increment (min)|
|`FANINIT` |`FINI`|set fans to high voltage for 3 sec at boot (0/1)| |`CINC`|`CINC`|catch time increment (min)|
|`BOFF` |`BOFF`|if set boost off will also turn the normal mode off (0/1)| |`RINC`|`RINC`|rise time increment (sec)|
|`BINC` |`BINC`|boost time increment (min)| |`OINC`|`OINC`|off timer increment (hour)|
|`CINC` |`CINC`|catch time increment (min)| |`RNDINC`|`RINC`|randon value increment (rpm)|
|`RINC` |`RINC`|rise time increment (sec)| |`CATCHSTOP`|`CSTP`|stop interval for stir fish catch function (ms)|
|`OINC` |`OINC`|off timer increment (hour)| |`PWM0`, `PWM1`||PWM output pins for fan speed|
|`RNDINC` |`RINC`|randon value increment (rpm)| |`PWM2`||PWM output pin for LCD brightness control|
|`CATCHSTOP` |`CSTP`|stop interval for stir fish catch function (ms)| |`I0`, `I1`||interrupts for rpm measurement (2 and 3 for Leonardo and ProMicro / 0 and 1 for Uno)|
|`PWM0`, `PWM1` | |PWM output pins for fan speed| |`SWAPENC`|`SWEN`|switch KY-040 encoder direxction (0/1)|
|`PWM2` | |PWM output pin for LCD brightness control| |`CLK`, `DT`, `SW`||pins for KY-040 encoder|
|`I0`, `I1` | |interrupts for rpm measurement (0/1 for Uno/Nano, 2/3 for Leonardo/ProMicro)| |`R0`, `R0`||voltage select relais pin|
|`SWAPENC` |`SWEN`|switch KY-040 encoder direxction (0/1)| |`RTHRES`|`RTHR`|voltage switch threshold (rpm)|
|`CLK`, `DT`, `SW`| |pins for KY-040 encoder| |`RINTERVAL`||regulation interval (ms)|
|`R0`, `R0` | |voltage select relais pin| |`RDELAY`||extra regulation delay when value changes (ms)|
|`RTHRES` |`RTHR`|voltage switch threshold (rpm)| |`RTOL`||regulation tolerance (rpm)|
|`RINTERVAL` |`XINT`|regulation interval (ms)| |`RNDINTERVL`|`RINT`|randon value range change interval (ms)|
|`RDELAY` |`XDEL`|extra regulation delay when value changes (ms)| |`SINTERVAL`||speed measurement interval (ms)|
|`RTOL` |`XTOL`|regulation tolerance (rpm)| |`SAVERAGE`||speed measurement average|
|`RNDINTERVL` |`RINT`|randon value range change interval (ms)| |`SAVETAG`||parameter save identifier|
|`SINTERVAL` |`SINT`|speed measurement interval (ms)| |`SAVEDELAY`||delay in seconds before parameter will be saved to EEPROM|
|`SAVERAGE` |`SAVG`|speed measurement average| |`LCDB`||LCD brightness steps (10 values, 0=off, 255=max)|
|`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|

124
stir.ino
View File

@ -3,9 +3,9 @@
#include <LiquidCrystal_I2C.h> #include <LiquidCrystal_I2C.h>
#define MS (long)millis() #define MS (long)millis()
#define NP 25 #define NP 19
String VERSION = "2.1.2"; String VERSION = "2.1.0";
int FANINIT = 0; // initialize fan with high voltage (0/1) int FANINIT = 0; // initialize fan with high voltage (0/1)
@ -37,7 +37,7 @@ 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 SWAPENC = 1; // swap encoder direction int SWAPENC = 1;
int CLK = 5; // clk on KY-040 encoder (swap clk and dt to invert 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
@ -47,20 +47,18 @@ 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)
int RINTERVAL = 50; // regulation internval (ds) long RINTERVAL = 5000; // regulation internval (ms)
int RDELAY = 30; // regulation delay on changes (ds) long RDELAY = 3000; // regulation delay on changes (ms)
int RTOL = 8; // regulation tolerance (rpm) int RTOL = 8; // regulation tolerance (rpm)
int RNDINTERVAL = 300; // randon value range change interval (sec) int RNDINTERVAL = 300; // randon value range change interval (sec)
int SINTERVAL = 20; // speed measurement internval (ds) long SINTERVAL = 2000; // speed measurement internval (ms)
int SAVERAGE = 4; // speed measurement average int SAVERAGE = 4; // speed measurement average
int SAVETAG = 2017; // save tag int SAVETAG = 2015; // 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 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)
@ -82,37 +80,28 @@ char form[8],out[20];
String CF[NP];int *P[NP],Cinc[NP],Cmin[NP],Cmax[NP]; // configuration menu String CF[NP];int *P[NP],Cinc[NP],Cmin[NP],Cmax[NP]; // configuration menu
int clkorg,dtorg; // encoder direction int clkorg,dtorg; // encoder direction
void(* resetFunc) (void) = 0;
void setup() { ////////////////////////////////////////////////////////////////////////////////////////// SETUP void setup() { ////////////////////////////////////////////////////////////////////////////////////////// SETUP
int i;
int i=0;
P[i]=&LGHT; CF[i]=F("LGHT"); defcon(i, 1, 0, 9 ); i++; i=0; P[i]=&LGHT; CF[i]="LGHT"; defcon(i, 1, 0, 9 ); // configuration menu setup
P[i]=&SPEEDINC1; CF[i]=F("SPI1"); defcon(i, 10, 10, 500 ); i++; i=1; P[i]=&SPEEDINC1; CF[i]="SPI1"; defcon(i, 10, 10, 500 );
P[i]=&SPEEDINC2; CF[i]=F("SPI2"); defcon(i, 10, 10, 500 ); i++; i=2; P[i]=&SPEEDINC2; CF[i]="SPI2"; defcon(i, 10, 10, 500 );
P[i]=&SPEEDINC3; CF[i]=F("SPI3"); defcon(i, 10, 10, 500 ); i++; i=3; P[i]=&SPEEDINC3; CF[i]="SPI3"; defcon(i, 10, 10, 500 );
P[i]=&SPEEDSTEP1; CF[i]=F("SPS1"); defcon(i, 50, 100, 2000 ); i++; i=4; P[i]=&SPEEDSTEP1; CF[i]="SPS1"; defcon(i, 50, 100, 2000 );
P[i]=&SPEEDSTEP2; CF[i]=F("SPS2"); defcon(i, 50, 100, 2000 ); i++; i=5; P[i]=&SPEEDSTEP2; CF[i]="SPS2"; defcon(i, 50, 100, 2000 );
P[i]=&SWAPENC; CF[i]=F("SWEN"); defcon(i, 1, 0, 1 ); i++; i=6; P[i]=&SWAPENC; CF[i]="SWEN"; defcon(i, 1, 0, 1 );
P[i]=&RNDINC; CF[i]=F("RINC"); defcon(i, 1, 0, 9 ); i++; i=7; P[i]=&RNDINC; CF[i]="RINC"; defcon(i, 1, 0, 9 );
P[i]=&CATCHSTOP; CF[i]=F("CSTP"); defcon(i, 10, 0, 1000 ); i++; i=8; P[i]=&CATCHSTOP; CF[i]="CSTP"; defcon(i, 10, 0, 1000 );
P[i]=&FANMIN; CF[i]=F("FMIN"); defcon(i, 50, 100, 1000 ); i++; i=9; P[i]=&FANMIN; CF[i]="FMIN"; defcon(i, 50, 100, 1000 );
P[i]=&FANMAX; CF[i]=F("FMAX"); defcon(i, 50, 500, 4000 ); i++; i=10; P[i]=&FANMAX; CF[i]="FMAX"; defcon(i, 50, 500, 4000 );
P[i]=&FANINIT; CF[i]=F("FINI"); defcon(i, 1, 0, 1 ); i++; i=11; P[i]=&FANINIT; CF[i]="FINI"; defcon(i, 1, 0, 1 );
P[i]=&RTHRES; CF[i]=F("RTHR"); defcon(i, 50, 0, 1500 ); i++; i=12; P[i]=&RTHRES; CF[i]="RTHR"; defcon(i, 50, 0, 1500 );
P[i]=&RNDINTERVAL; CF[i]=F("RINT"); defcon(i, 1, 0, 60 ); i++; i=13; P[i]=&RNDINTERVAL; CF[i]="RINT"; defcon(i, 1, 0, 60 );
P[i]=&BOFF; CF[i]=F("BOFF"); defcon(i, 1, 0, 1 ); i++; i=14; P[i]=&BOFF; CF[i]="BOFF"; defcon(i, 1, 0, 1 );
P[i]=&BINC; CF[i]=F("BINC"); defcon(i, 1, 1, 60 ); i++; i=15; P[i]=&BINC; CF[i]="BINC"; defcon(i, 1, 1, 60 );
P[i]=&CINC; CF[i]=F("CINC"); defcon(i, 1, 1, 60 ); i++; i=16; P[i]=&CINC; CF[i]="CINC"; defcon(i, 1, 1, 60 );
P[i]=&RINC; CF[i]=F("RINC"); defcon(i, 1, 1, 60 ); i++; i=17; P[i]=&RINC; CF[i]="RINC"; defcon(i, 1, 1, 60 );
P[i]=&OINC; CF[i]=F("OINC"); defcon(i, 1, 1, 60 ); i++; i=18; P[i]=&OINC; CF[i]="OINC"; defcon(i, 1, 1, 60 );
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
@ -141,13 +130,15 @@ void setup() { /////////////////////////////////////////////////////////////////
for (i=0;i<NP;i++) *P[i]=eer(200+i); for (i=0;i<NP;i++) *P[i]=eer(200+i);
} }
clkorg=CLK;dtorg=DT;if (SWAPENC) {;DT=clkorg;CLK=dtorg;} // swap encoder direction clkorg=CLK;dtorg=DT;
if (SWAPENC) {;DT=clkorg;CLK=dtorg;}
lset(); lset();
enclast=digitalRead(CLK); // get encoder state enclast=digitalRead(CLK); // get encoder state
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 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
@ -184,12 +175,12 @@ void loop() { //////////////////////////////////////////////////////////////////
} }
if (MS-xts>(SINTERVAL*100)) { ///////////////////////////////////////////////////////////// speed measurement 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; 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*100)) { ////////////////////////////////////////////////////////////// speed regulation if (MS-rts>RINTERVAL) { //////////////////////////////////////////////////////////////////// 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;
@ -232,7 +223,6 @@ void loop() { //////////////////////////////////////////////////////////////////
M=2;save();updatemarker(); M=2;save();updatemarker();
if (SWAPENC) {;DT=clkorg;CLK=dtorg;} if (SWAPENC) {;DT=clkorg;CLK=dtorg;}
else {;DT=dtorg;CLK=clkorg;} else {;DT=dtorg;CLK=clkorg;}
if (RESET==1) {;RESET=0;eew(0,0);save();resetFunc();}
} }
} }
@ -266,8 +256,7 @@ void loop() { //////////////////////////////////////////////////////////////////
if (S==6) otime[M]+=OINC; // off time up if (S==6) otime[M]+=OINC; // off time up
if (S==7) rnval[M]+=RNDINC; // random value if (S==7) rnval[M]+=RNDINC; // random value
if (S==8 && M==0) C++; // increase config menu 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]);
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
@ -281,15 +270,14 @@ void loop() { //////////////////////////////////////////////////////////////////
if (S==6) otime[M]-=OINC; // off time down if (S==6) otime[M]-=OINC; // off time down
if (S==7) rnval[M]-=RNDINC; // random value if (S==7) rnval[M]-=RNDINC; // random value
if (S==8 && M==0) C--; // decrease config menu 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]);
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*100);} // apply (boost) speed change 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==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
@ -299,7 +287,7 @@ void loop() { //////////////////////////////////////////////////////////////////
if (S==8 && C==0) lset(); // set LCD brightness if (S==8 && C==0) lset(); // set LCD brightness
} }
C=cut(C,0,NP-1); // check configuration mode C=cut(C,0,18); // check cfg mode
if (M==2) S=cut(S,0,8); // check menu mode if (M==2) S=cut(S,0,8); // check menu mode
@ -342,7 +330,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*100);F[n]=1;catts[n]=vts[n]=MS;r[n]=0; rts=MS+RDELAY;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;
} }
@ -352,9 +340,9 @@ 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*100);bstate[n]=1;bts[n]=MS;F[n]=1;vts[n]=MS; rts=MS+RDELAY;bstate[n]=1;bts[n]=MS;F[n]=1;vts[n]=MS;
} else { } else {
bstate[n]=0;rts=MS+(RDELAY*100); bstate[n]=0;rts=MS+RDELAY;
} }
updatePWM(); updatePWM();
SAVE++; SAVE++;
@ -363,31 +351,31 @@ void bset(int n,int s) { ///////////////////////////////////////////////////////
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,F("SPEED"));ilcd(7+i*5,1,-4,v[i]);} if (S==0) {;slcd(1,1,5,"SPEED");ilcd(7+i*5,1,-4,v[i]);}
if (S==1) {;slcd(1,1,5,F("BOOST"));ilcd(7+i*5,1,-4,int(b[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,F("BTIME"));ilcd(7+i*5,1,-4,int(btime[i]));} if (S==2) {;slcd(1,1,5,"BTIME");ilcd(7+i*5,1,-4,int(btime[i]));}
if (S==3) { if (S==3) {
slcd(1,1,5,F("CATCH")); slcd(1,1,5,"CATCH");
if (cat[i]==0) slcd( 7+i*5,1,-4,F("OFF")); else slcd( 7+i*5,1,-3,F("ON")); 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,F("CTIME"));ilcd(7+i*5,1,-4,int(ctime[i]));} if (S==4) {;slcd(1,1,5,"CTIME");ilcd(7+i*5,1,-4,int(ctime[i]));}
if (S==5) {;slcd(1,1,5,F("RTIME"));ilcd(7+i*5,1,-4,int(rtime[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,F("OTIME"));ilcd(7+i*5,1,-4,int(otime[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,F("RNVAL"));ilcd(7+i*5,1,-4,int(rnval[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,F("CFG"));slcd(7,1,-4,CF[C]);ilcd(7+5,1,-4,*P[C]);} if (S==8) {;slcd(1,1,-5,"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,F(" "));slcd(6,1,1,F(" "));slcd(11,1,1,F(" ")); slcd(0,1,1," ");slcd(6,1,1," ");slcd(11,1,1," ");
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,F(" ")); if (bclr) slcd(0,0,6," ");
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,F("CAT")); if (cstate[i]) slcd(7+i*5,0,-4,"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);
@ -397,7 +385,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,F("OFF")); } else slcd(7+i*5,0,-4,"OFF");
} }
} }
} }
@ -436,10 +424,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 ((bstate[0]?b[0]:v[0])>=RTHRES) digitalWrite(R0,LOW); if (v[0]>=RTHRES) digitalWrite(R0,LOW);
else digitalWrite(R0,HIGH); else digitalWrite(R0,HIGH);
if ((bstate[1]?b[1]:v[1])>=RTHRES) digitalWrite(R1,LOW); if (v[1]>=RTHRES) digitalWrite(R1,LOW);
else digitalWrite(R1,HIGH); else digitalWrite(R1,HIGH);
} }