From 217f838e07b8bce57e22dc4d8288c6d780ca4807 Mon Sep 17 00:00:00 2001 From: Michael Wesemann Date: Sat, 9 Mar 2019 15:09:06 +0100 Subject: [PATCH] code cleanup, bug fixes, API --- README.md | 2 + stir.ino | 378 +++++++++++++++++++++++++++--------------------------- 2 files changed, 191 insertions(+), 189 deletions(-) diff --git a/README.md b/README.md index 0b9f413..65eda5a 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,8 @@ All functions are controlled by the KY-040 encoder: |RTOL|regulation tolerance (rpm)| |SINTERVAL|speed measurement interval (ms)| |SAVERAGE|speed measurement average| +|SAVETAG|parameter save identifier| +|SAVEDELAY|delay in seconds before parameter will be saved to EEPROM| ## Schematics diff --git a/stir.ino b/stir.ino index a2013c0..4d3d8b2 100644 --- a/stir.ino +++ b/stir.ino @@ -1,15 +1,20 @@ -/////////////////////////////////////////////////////////////////////////////// Stir Control (mwx'2019, v1.4.0) +/////////////////////////////////////////////////////////////////////////////////////// Stir Control (mwx'2019) #include #include + #define MS (long)millis() +#define SX Serial.print +#define SXN Serial.println + +String VERSION = "1.5.0"; int SPEEDINC = 50; // speed increment (rpm) -int FANMIN = 200; // fan minimum speed (rpm) -int FANMAX = 1600; // fan maximum speed (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 CATCHSTOP = 20000; // catch stop period (ms) +int CATCHSTOP = 20000; // fish catch stop period (ms) int PWM0 = 9; // PWM pin for 1. fan int PWM1 = 10; // PWM pin for 2. fan @@ -31,30 +36,27 @@ int SAVERAGE = 4; int SAVETAG = 1007; // save tag int SAVEDELAY = 60000; // EEPROM save delay (ms) -byte aright[] = {0x00,0x08,0x0C,0x0E,0x0C,0x08,0x00,0x00}; // LCD character -byte aup[] = {0x04,0x0E,0x1F,0x00,0x00,0x00,0x00,0x00}; +byte aright[] = {0x00,0x08,0x0C,0x0E,0x0C,0x08,0x00,0x00}; // LCD character +byte aup[] = {0x04,0x0E,0x1F,0x00,0x00,0x00,0x00,0x00}; LiquidCrystal_I2C lcd(0x27,16,2); // LCD display (connect to SDA/SCL) -int i,v0,b0,r0,v1,b1,r1,fanstate0,fanstate1; // speed and regulation -double r,rx,rpm0,rpm1,xpm0,xpm1,xb0,xb1,xv0,xv1,rtime0,rtime1; -long rpmcount0,rpmcount1,speedcount0,speedcount1; // interrupt rpm counter -long xts,sts,rts,swts,bts,ox,savets,catchts0,catchts1,stop0,stop1,b0ts,b1ts,v0ts,v1ts; // timing -int bdelay,bprocess,enclast,encval,swmode,mode; // button/encoder processing -int bstate0,bstate1,btime0,btime1,catch0,catch1,ctime0,ctime1,cstate0,cstate1,SAVE,LOCK; // operating states +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]; // 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},SAVE=0,LOCK=0; // operating states char form[8],out[20]; // string buffer +String cmd[8];int icmd[8]; - -void setup() { ////////////////////////////////////////////////////////////////////////////////////////// SETUP - rpmcount0=0;rpmcount1=0;speedcount0=0;speedcount1=0;rpm0=0;rpm1=0;xpm0=0;xpm1=0; - bprocess=0;r0=0;r1=0;swmode=2;cstate0=0;cstate1=0; - +void setup() { ////////////////////////////////////////////////////////////////////////////////////////// SETUP Serial.begin(9600); // start serial lcd.init();lcd.clear();lcd.backlight();lcd.createChar(0,aright);lcd.createChar(1,aup); // initialize lcd pinMode(PWM0,OUTPUT);pinMode(PWM1,OUTPUT); // set PWM pins pinMode(CLK,INPUT);pinMode(DT,INPUT);pinMode(SW,INPUT); // set KY-040 pins + digitalWrite(CLK,true);digitalWrite(DT,true);digitalWrite(SW,true); // turn ON pullup resistors attachInterrupt(I0,rpmint0,FALLING); // setup interrupts vor rpm in attachInterrupt(I1,rpmint1,FALLING); @@ -64,123 +66,117 @@ void setup() { ///////////////////////////////////////////////////////////////// SAVE=0; // load/initialize settings if (eer(0)!=SAVETAG) { - v0=300;v1=300;b0=700;b1=700;btime0=30;btime1=30;catch0=0;catch1=0; - ctime0=120;ctime1=120;rtime0=60;rtime1=60;fanstate0=0;fanstate1=0; + 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;} eew(0,SAVETAG);save(); } else { - v0=eer(1);v1=eer(2);b0=eer(3);b1=eer(4);btime0=eer(5);btime1=eer(6);catch0=eer(7);catch1=eer(8); - ctime0=eer(9);ctime1=eer(10);fanstate0=eer(11);fanstate1=eer(12);rtime0=eer(13);rtime1=eer(14); + 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); + } } enclast=digitalRead(CLK); // get encoder state - xts=sts=rts=swts=bts=savets=catchts0=catchts1=stop0=stop1=v0ts=v1ts=MS; // set timer - bstate0=0;bstate1=0;mode=0;updatePWM();updatelcd();updatespeed();updatemarker();LOCK=0; // set initial states + for (int i=0;i<2;i++) catts[i]=stop[i]=vts[i]=MS;xts=sts=rts=swts=buts=savets=MS; // timer + updatePWM();updatelcd();updatespeed();updatemarker(); // update all } void loop() { //////////////////////////////////////////////////////////////////////////////////////////// LOOP - if (SAVE>0 && MS-savets>SAVEDELAY) {;save();SAVE=0;savets=MS;} ////////////////////// save settings if needed - - if (catch0 && MS-catchts0>(long)ctime0*60000 && fanstate0==1) { ///////////////////////// initiate catch fish - catchts0=MS;cstate0=1;fanstate0=0;stop0=MS;updatePWM();updatespeed(); - } - if (catch1 && MS-catchts1>(long)ctime1*60000 && fanstate1==1) { - catchts1=MS;cstate1=1;fanstate1=0;stop1=MS;updatePWM();updatespeed(); - } - - if (cstate0 && MS-stop0>CATCHSTOP && fanstate0==0) { ///////////////////////// stop catch fish and start over - cstate0=0;fanstate0=1;v0ts=MS;rts=MS+2000;updatePWM();updatespeed(); - } - - if (cstate1 && MS-stop1>CATCHSTOP && fanstate1==0) { - cstate1=0;fanstate1=1;v1ts=MS;rts=MS+2000;updatePWM();updatespeed(); + if (Serial.available() > 0) { ////////////////////////////////////////////////////////// serial communication + int n=cutcmd(Serial.readString()); + int err=1; + if (cmd[0]=="info" && n==1) {;err=0;} + if (cmd[0]=="version" && n==1) {;SXN(VERSION);return;} + if (cmd[0]=="speed" && n==3) {;v[icmd[1]]=cut(icmd[2],FANMIN,FANMAX);err=0;} + if (cmd[0]=="bspeed" && n==3) {;b[icmd[1]]=cut(icmd[2],FANMIN,FANMAX);err=0;} + if (cmd[0]=="btime" && n==3) {;btime[icmd[1]]=cut(icmd[2],0,60);err=0;} + if (cmd[0]=="ctime" && n==3) {;ctime[icmd[1]]=cut(icmd[2],60,240);err=0;} + if (cmd[0]=="rtime" && n==3) {;rtime[icmd[1]]=cut(icmd[2],0,240);err=0;} + if (cmd[0]=="catch" && n==3) {;cat[icmd[1]]=cut(icmd[2],0,1);catts[0]=MS;err=0;} + if (cmd[0]=="on" && n==2) {;fset(cut(icmd[1],0,1),1);err=0;} + if (cmd[0]=="off" && n==2) {;fset(cut(icmd[1],0,1),0);err=0;} + if (cmd[0]=="bon" && n==2) {;bset(cut(icmd[1],0,1),1);err=0;} + if (cmd[0]=="boff" && n==2) {;bset(cut(icmd[1],0,1),0);err=0;} + 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(VERSION);SX(":");SXN(err); } - if (bstate0 && MS-b0ts>(long)btime0*60000) {;bstate0=0;mode=0;updatelcd();} /////////////// check boost state - if (bstate1 && MS-b1ts>(long)btime1*60000) {;bstate1=0;mode=0;updatelcd();} + if (SAVE>0 && MS-savets>SAVEDELAY) {;save();SAVE=0;savets=MS;} ////////////////////// save settings if needed + + for (int i=0;i<2;i++) { + + 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 - xpm0=xpm0*(SAVERAGE-1)/SAVERAGE+(speedcount0/((MS-xts)/1000.0)*30.0)/SAVERAGE; - xpm1=xpm1*(SAVERAGE-1)/SAVERAGE+(speedcount1/((MS-xts)/1000.0)*30.0)/SAVERAGE; - updatespeed();xts=MS;speedcount0=0;speedcount1=0; + 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 - rpm0=rpmcount0/((MS-sts)/1000.0)*30.0; - rpm1=rpmcount1/((MS-sts)/1000.0)*30.0; - sts=MS;rpmcount0=0;rpmcount1=0; - - calcramp(); - - if (!fanstate0) {;r0=0;OCR1A=0;} - else { - r=(bstate0?xb0:xv0)-rpm0; - if (abs(r)>RTOL) r0=r<0?r0-1-abs(r)/10:r0+1+abs(r)/10; - OCR1A=cut((bstate0?xb0:xv0)/(FANMAX/320.0)+r0,0,320); + 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)); + } } - if (!fanstate1) {;r1=0;OCR1B=0;} - else { - r=(bstate1?xb1:xv1)-rpm1; - if (abs(r)>RTOL) r1=r<0?r1-1-abs(r)/10:r1+1+abs(r)/10; - OCR1B=cut((bstate1?xb1:xv1)/(FANMAX/320.0)+r1,0,320); - } - - updatespeed();rts=MS; + sts=MS;rts=MS; + updatespeed(); } bdelay=0; //////////////////////////////////////////////////////////////////////////////////// process switch if (!bprocess) { while (!digitalRead(SW)){ - bdelay++; - delay(25); - bprocess=1; - if (bdelay>20) break; + bdelay++;delay(25);bprocess=1;if (bdelay>20) break; } } - if (bdelay>0 && MS-bts>100) { // long button press + if (bdelay>0 && MS-buts>100) { // long button press if (bdelay>20) { - if (swmode==0 && mode==0 && !LOCK) { // fan 0 on/off - if (fanstate0==0) {;rts=MS+RDELAY;fanstate0=1;catchts0=v0ts=MS;r0=0;updatePWM();} - else {;fanstate0=0;bstate0=0;} - } - - if (swmode==1 && mode==0 && !LOCK) { // fan 1 on/off - if (fanstate1==0) {;rts=MS+RDELAY;fanstate1=1;catchts1=v1ts=MS;r1=0;updatePWM();} - else {;fanstate1=0;bstate1=0;} - } - - if (swmode==0 && mode==1 && !LOCK) { // boost fan 0 on/off - if (bstate0==0) {;rts=MS+RDELAY;bstate0=1;b0ts=MS;fanstate0=1;v0ts=MS;} - else {;bstate0=0;rts=MS+RDELAY+2000;updatePWM();} - } - - if (swmode==1 && mode==1 && !LOCK) { // boost fan 1 on/off - if (bstate1==0) {;rts=MS+RDELAY;bstate1=1;b1ts=MS;fanstate1=1;v1ts=MS;} - else {;bstate1=0;rts=MS+RDELAY+2000;updatePWM();} - } - - if (swmode==2) { // lock/unlock + if (M==2) { // lock/unlock if (LOCK==0) LOCK=1; else LOCK=0; - updatemarker(); - save(); + updatemarker();save(); + } 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); + } } - updatespeed(); - bdelay=0; + updatespeed();bdelay=0; } else if (bdelay>0 && bdelay<20 && !LOCK) { // short button press, switch: menu -> fan 0 -> fan 1 - swmode++;if (swmode>2) swmode=0; + M++;if (M>2) M=0; updatemarker(); bdelay=0; } - SAVE++;bts=MS; + SAVE++;buts=MS; } if (digitalRead(SW)) bprocess=0; @@ -189,53 +185,38 @@ void loop() { ////////////////////////////////////////////////////////////////// if(!encval){ if (digitalRead(DT) != encval) { // turn encoder clockwise - if (swmode==0 && mode==0) v0+=SPEEDINC; // fan 0 speed up - if (swmode==1 && mode==0) v1+=SPEEDINC; // fan 1 speed up - if (swmode==0 && mode==1) b0+=SPEEDINC; // boost 0 speed up - if (swmode==1 && mode==1) b1+=SPEEDINC; // boost 1 speed up - if (swmode==0 && mode==2) btime0++; // boost time 0 up - if (swmode==1 && mode==2) btime1++; // boost time 1 up - if (swmode==0 && mode==3) catch0++; // catch 0 on/off - if (swmode==1 && mode==3) catch1++; // catch 1 on/off - if (swmode==0 && mode==4) ctime0+=10; // catch time 0 up - if (swmode==1 && mode==4) ctime1+=10; // catch time 1 up - if (swmode==0 && mode==5) rtime0+=10; // rise time 0 up - if (swmode==1 && mode==5) rtime1+=10; // rise time 1 up - if (swmode==2) mode++; // scroll menu + if (M==2) S++; // scroll menu + else { + if (S==0) v[M]+=SPEEDINC; // fan 0 speed up + if (S==1) b[M]+=SPEEDINC; // boost 0 speed up + if (S==2) btime[M]++; // boost time 0 up + if (S==3) cat[M]++; // cat 0 on/off + if (S==4) ctime[M]+=10; // cat time 0 up + if (S==5) rtime[M]+=10; // rise time 0 up + } } else { // turn encoder counterclockwise - if (swmode==0 && mode==0) v0-=SPEEDINC; // fan 0 speed down - if (swmode==1 && mode==0) v1-=SPEEDINC; // fan 1 speed down - if (swmode==0 && mode==1) b0-=SPEEDINC; // boost 0 speed down - if (swmode==1 && mode==1) b1-=SPEEDINC; // boost 1 speed down - if (swmode==0 && mode==2) btime0--; // boost time 0 down - if (swmode==1 && mode==2) btime1--; // boost time 1 down - if (swmode==0 && mode==3) catch0--; // catch 0 on/off - if (swmode==1 && mode==3) catch1--; // catch 1 on/off - if (swmode==0 && mode==4) ctime0-=10; // catch time 0 down - if (swmode==1 && mode==4) ctime1-=10; // catch time 1 down - if (swmode==0 && mode==5) rtime0-=10; // rise time 0 down - if (swmode==1 && mode==5) rtime1-=10; // rise time 1 down - if (swmode==2) mode--; // scroll menu + if (M==2) S--; // scroll menu + else { + if (S==0) v[M]-=SPEEDINC; // fan 0 speed down + if (S==1) b[M]-=SPEEDINC; // boost 0 speed down + if (S==2) btime[M]--; // boost time 0 down + if (S==3) cat[M]--; // cat 0 on/off + if (S==4) ctime[M]-=10; // cat time 0 down + if (S==5) rtime[M]-=10; // rise time 0 down + } } - - if (swmode==0 && mode<=1) {;updatePWM();rts=MS+RDELAY;} // apply (boost) speed change fan 0 - if (swmode==1 && mode<=1) {;updatePWM();rts=MS+RDELAY;} // apply (boost) speed change fan 1 - if (b0max?max:vmax?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 - eew(1,v0);eew(2,v1);eew(3,b0);eew(4,b1);eew(5,btime0);eew(6,btime1);eew(7,catch0);eew(8,catch1); - eew(9,ctime0);eew(10,ctime1);eew(11,fanstate0);eew(12,fanstate1);eew(13,rtime0);eew(14,rtime1); + 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]); + } +} + +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