Re: Der Magnetrührer-Thread (DIY, Infos, Bilder und mehr)
Verfasst: Samstag 9. Februar 2019, 20:54
Sieht echt gut aus.
Gruß JackFrost
Gruß JackFrost
habe ich noch nicht probiert. Die Regelung habe ich aber inzwischen verbessert.
Hab meinen Rührer dann mal aufgeschraubt, aber leider vergessen auch Fotos von den Rührfischen zu machen...DerDerDasBierBraut hat geschrieben: ↑ Schraub mal auf und mach Fotos (mit und ohne Fisch). Das bekommen wir gelöst.
Magnete hab ich. Danke.Frudel hat geschrieben: ↑Montag 11. Februar 2019, 14:10 Klasse Teil , bin begeistert!
Musste nachfragen , wieviel der Versand nach Osterlitsch kostet , bei Ebä gibt es einige , die die Magneten anbieten.
https://www.ebay.de/itm/5-X-POWER-NEODY ... 9#shpCntId
Ja, das kann ich gerne machen. Allerdings wird das immer ein Bastelprojekt bleiben. Wer das nachbauen will sollte also schon halbwegs Sattelfest im Umgang mit Arduino und Raspberry Pi sein. Ich helfe da gerne so gut ich kann das ist aber per Ferndiagnose oft schwierig.
Jack, ich habe auch nicht so gute Möglichkeiten. So schwierig ist das nicht. Das Holz habe ich fertig zugeschnitten bestellt, die Glasscheibe auch. Etwas fummelig ist das rechteckige Loch (habe das mit eine Minifräse gemacht, geht aber auch sicher mit Laubsäge oder Dremel. Den 3D gedruckten Rahmen stelle ich gerne zur Verfügung). Für alles andere reicht ein Akkuschrauber.JackFrost hat geschrieben: ↑Montag 11. Februar 2019, 16:41 Da meine Möglichkeiten zur Bearbeitung von Holz, Kunststoff und Metall nicht so gut sind ... Mit dem Holzgehäuse kann ich bei weitem nicht mithalten.
Meine Smart-Funktionen werden sich auf Automatik und Fernsteurung über USB/RS232 TTL beschränken.
Mit einem Magneten wedelt der Rührfisch wie ein Fuchsschwanz. Das kann nicht funktionieren!murby81 hat geschrieben: ↑Dienstag 12. Februar 2019, 20:14 Liegt es an der fehlenden Steuerung? Lüfter hat 1350 U/Min, ist das zuviel? Hab schon 5V und 12V getestet. Leider immer das selbe Ergebnis. Oder doch ein anderes Problem? Magnet zu groß oder falsch angebracht? (Mittig am Lüfterrad angebracht)
Code: Alles auswählen
/////////////////////////////////////////////////////////////////////////////// Stir Control (mwx'2019, v1.2.1)
#include <EEPROM.h>
#include <LiquidCrystal_I2C.h>
#define SX Serial.print
#define SXN Serial.println
#define MS (long)millis()
int SPEEDINC = 50; // speed increment
int FANMIN = 200; // fan minimum speed
int FANMAX = 1000; // fan maximum speed
int RINTERVAL = 3000; // regulation interval
int RDELAY = 2000; // regulation delay on changes
int CATCHSTOP = 20000; // catch stop period
int PWM0 = 9; // PWM pin for 1. fan
int PWM1 = 10; // PWM pin for 2. fan
int I0 = 2; // interrupt pin for 1. fan rpm signal
int I1 = 3; // interrupt pin for 2. fan rpm signal
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 SAVETAG = 1004; // save tag
LiquidCrystal_I2C lcd(0x27,16,2); // LCD display (connect to SDA/SCL)
int v0,b0,r0,v1,b1,r1,r,fanstate0,fanstate1; // speed and regulation
long rpmcount0,rpmcount1; // rpm counter
double rpm0,rpm1; // rpm
long speedts,dt,rts,swts,bts,ox,savets,catchts0,catchts1,stop0,stop1,b0ts,b1ts; // timing
int bdelay,bprocess,enclast,encval,swmode; // button processing
char form[8],out[32],M[8];String str; // string buffer
int OK,SAVE,LOCK,bstate0,bstate1,btime0,btime1,catch0,catch1,ctime0,ctime1,mode;
void setup() { ////////////////////////////////////////////////////////////////////////////////////////// SETUP
rpmcount0=0;rpmcount1=0;rpm0=0;rpm1=0;bprocess=0;speedts=0;r0=0;r1=0;swmode=2;
Serial.begin(9600); // start serial
lcd.init();lcd.backlight();lcd.clear(); // initialize lcd
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) // non-inverted PWM on ch. A
| _BV(COM1B1) // same on ch; B
| _BV(WGM11); // mode 10: ph. correct PWM, TOP=ICR1
TCCR1B = _BV(WGM13) // ditto
| _BV(CS10); // prescaler=1
ICR1 = 320; // TOP=320
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;
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);
}
pinMode(PWM0,OUTPUT);pinMode(PWM1,OUTPUT); // set pin modes
pinMode(CLK,INPUT);pinMode(DT,INPUT);pinMode(SW,INPUT);
enclast=digitalRead(CLK); // get encoder state
fanstate0=0;fanstate1=0;OCR1A=0;OCR1B=0; // turn fans off
rts=MS;swts=MS;bts=MS;savets=MS;catchts0=MS;catchts1=MS;stop0=MS;stop1=MS; // set timer
lcd.clear(); // clear display, start running
bstate0=0;bstate1=0;mode=0;updatelcd();updatespeed();updatemarker();LOCK=0; // set initial states
}
void loop() { //////////////////////////////////////////////////////////////////////////////////////////// LOOP
if (SAVE>0 && MS-savets>60000) {;save();SAVE=0;savets=MS;} ////////////////////////// save settings if needed
if (catch0 && MS-catchts0>(long)ctime0*60000) { ////////////////////////////////////// check catch fish state
catchts0=MS;stop0=MS+CATCHSTOP;
updatePWM();
}
if (catch1 && MS-catchts1>(long)ctime1*60000) {
catchts1=MS;stop1=MS+CATCHSTOP;
updatePWM();
}
if (bstate0 && MS-b0ts>(long)btime0*60000) {;bstate0=0;updatelcd();} ////////////////////// check boost state
if (bstate1 && MS-b1ts>(long)btime0*60000) {;bstate1=0;updatelcd();}
if (Serial.available() > 0) { ////////////////////////////////////////////////////////// serial communication
str=Serial.readString();OK=0;
if (str=="info") {;serinfo();OK=1;} // info
if (str.substring(0,5)=="speed") { // speed <fan0> <fan1>
v0=sstr(str,':',1).toInt();
v1=sstr(str,':',2).toInt();
updatePWM();r0=0;r1=0;rts=MS+RDELAY;
SAVE++;OK=1;updatelcd();serinfo();
}
if (str.substring(0,6)=="bspeed") { // bspeed <fan0> <fan1>
b0=sstr(str,':',1).toInt();
b1=sstr(str,':',2).toInt();
updatePWM();r0=0;r1=0;rts=MS+RDELAY;
SAVE++;OK=1;updatelcd();updatespeed();serinfo();
}
if (str.substring(0,2)=="on") { // on <fan0> <fan1> (value: 0 or 1)
if (sstr(str,':',1).toInt()==1) {;fanstate0=1;r0=0;} else fanstate0=0;
if (sstr(str,':',2).toInt()==1) {;fanstate1=1;r1=0;} else fanstate1=0;
updatePWM();rts=MS+RDELAY;
SAVE++;OK=1;updatelcd();updatespeed();serinfo();
}
if (str.substring(0,5)=="boost") { // boost <fan0> <fan1> (value: 0 or 1)
if (sstr(str,':',1).toInt()==1) {;rts=MS+RDELAY;bstate0=1;b0ts=MS;} else {;bstate0=0;}
if (sstr(str,':',2).toInt()==1) {;rts=MS+RDELAY;bstate1=1;b1ts=MS;} else {;bstate1=0;}
SAVE++;OK=1;updatelcd();updatespeed();serinfo();
}
if (str.substring(0,5)=="catch") { // catch <fan0> <fan1> (value: 0 or 1)
if (sstr(str,':',1).toInt()==1) {;catch0=1;catchts0=MS;} else {;catch0=0;}
if (sstr(str,':',2).toInt()==1) {;catch1=1;catchts1=MS;} else {;catch1=0;}
SAVE++;OK=1;updatelcd();updatespeed();serinfo();
}
if (str.substring(0,5)=="btime") { // btime <fan0> <fan1> (value: 0-60)
btime0=sstr(str,':',1).toInt();if (btime0<0) btime0=0;if (btime0>60) btime0=60;
btime1=sstr(str,':',2).toInt();if (btime1<0) btime1=0;if (btime1>60) btime1=60;
SAVE++;OK=1;updatelcd();updatespeed();serinfo();
}
if (str.substring(0,5)=="ctime") { // ctime <fan0> <fan1> (value: 60-240)
ctime0=sstr(str,':',1).toInt();if (ctime0<60) ctime0=60;if (ctime0>240) ctime0=240;
ctime1=sstr(str,':',2).toInt();if (ctime1<60) ctime1=60;if (ctime1>240) ctime1=240;
SAVE++;OK=1;updatelcd();updatespeed();serinfo();
}
if (!OK) SXN("ERROR");
}
if (MS-rts>RINTERVAL) { ////////////////////////////////////////////////////////////////////////// regulation
rpm0=rpmcount0/2/((MS-speedts)/1000.0)*60.0;
rpm1=rpmcount1/2/((MS-speedts)/1000.0)*60.0;
speedts=MS;rpmcount0=0;rpmcount1=0;
if (abs(v0-rpm0)>8) {
ox=1;if (abs(v0-rpm0)>20) ox=3;if (abs(v0-rpm0)>50) ox=5;
if (bstate0) r=b0; else r=v0;
if (r>rpm0) {;r0+=ox;if (r0>40) r0=40;}
if (r<rpm0) {;r0-=ox;if (r0<-40) r0=-40;}
}
if (abs(v1-rpm1)>8) {
ox=1;if (abs(v1-rpm1)>20) ox=3;if (abs(v1-rpm1)>50) ox=5;
if (bstate1) r=b1; else r=v1;
if (r>rpm1) {;r1+=ox;if (r1>40) r1=40;}
if (r<rpm1) {;r1-=ox;if (r1<-40) r1=-40;}
}
if (!fanstate0) r0=0;
if (!fanstate1) r1=0;
updatePWM();updatespeed();rts=MS;
}
bdelay=0; //////////////////////////////////////////////////////////////////////////////////// process switch
if (!bprocess) {
while (!digitalRead(SW)){
bdelay++;
delay(25);
bprocess=1;
if (bdelay>20) break;
}
}
if (bdelay>0 && MS-bts>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;r0=0;updatePWM();}
else {;fanstate0=0;}
updatespeed();
}
if (swmode==1 && mode==0 && !LOCK) { // fan 1 on/off
if (fanstate1==0) {;rts=MS+RDELAY;fanstate1=1;r1=0;updatePWM();}
else {;fanstate1=0;}
updatespeed();
}
if (swmode==0 && mode==1 && !LOCK) { // boost 0 on/off
if (bstate0==0) {
rts=MS+RDELAY;bstate0=1;b0ts=MS;updatePWM();
} else {;bstate0=0;}
updatespeed();
}
if (swmode==1 && mode==1 && !LOCK) { // boost 1 on/off
if (bstate1==0) {
rts=MS+RDELAY;bstate1=1;b1ts=MS;updatePWM();
} else {;bstate1=0;}
updatespeed();
}
if (swmode==2) { // lock/unlock
if (LOCK==0) LOCK=1;
else LOCK=0;
updatemarker();
}
bdelay=0;
} else if (bdelay>0 && bdelay<20 && !LOCK) { // short button press: switch menu -> fan 0 -> fan 1
swmode++;if (swmode>2) swmode=0;
updatemarker();
bdelay=0;
}
bts=MS;
}
if (digitalRead(SW)) bprocess=0;
encval = digitalRead(CLK); ////////////////////////////////////////////////////////////////// process encoder
if (encval != enclast && !LOCK) {
if(!encval){
if (digitalRead(DT) != encval) { // cw
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==2) mode++;
} else { // ccw
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==2) mode--;
}
if (swmode==0 && mode==0) {;updatePWM();r0=0;rts=MS+RDELAY;} // apply speed change 0
if (swmode==1 && mode==0) {;updatePWM();r1=0;rts=MS+RDELAY;} // apply speed change 1
if (swmode==0 && mode==1) {;updatePWM();r0=0;rts=MS+RDELAY;} // apply boost speed change 0
if (swmode==1 && mode==1) {;updatePWM();r1=0;rts=MS+RDELAY;} // apply boost speed change 1
if (swmode==0 && mode==2) {;if (btime0<0) btime0=0;if (btime0>60) btime0=60;} // check boost time 0
if (swmode==1 && mode==2) {;if (btime1<0) btime1=0;if (btime1>60) btime1=60;} // check boost time 1
if (swmode==0 && mode==3) {;if (catch0<0) catch0=1;if (catch0>1) catch0=0;catchts0=MS;} // check catch 0
if (swmode==1 && mode==3) {;if (catch1<0) catch1=0;if (catch1>1) catch1=0;catchts1=MS;} // check catch 1
if (swmode==0 && mode==4) {;if (ctime0<60) ctime0=60;if (ctime0>240) ctime0=240;} // check boost time 0
if (swmode==1 && mode==4) {;if (ctime1<60) ctime1=60;if (ctime1>240) ctime1=240;} // check boost time 1
if (swmode==2) {;if (mode<0) mode=4;if (mode>4) mode=0;} // check menu mode
SAVE++;updatelcd();delay(50);
}
}
enclast=encval;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////// SUPPORT
void updatelcd() { ///////////////////////////////////////////////////////////////////////////////// update LCD
if (mode==0) {
slcd(1,1,5,"SPEED");
ilcd(7,1,-4,int(v0));
ilcd(12,1,-4,int(v1));
}
if (mode==1) {
slcd(1,1,5,"BOOST");
ilcd(7,1,-4,int(b0));
ilcd(12,1,-4,int(b1));
}
if (mode==2) {
slcd(1,1,5,"BTIME");
ilcd(7,1,-4,int(btime0));ilcd(12,1,-4,int(btime1));
}
if (mode==3) {
slcd(1,1,5,"CATCH");
if (catch0==0) slcd(7,1,-4,"OFF");
else slcd(7,1,-3,"ON");
if (catch1==0) slcd(12,1,-4,"OFF");
else slcd(12,1,-3,"ON");
}
if (mode==4) {
slcd(1,1,5,"CTIME");
ilcd(7,1,-4,int(ctime0));ilcd(12,1,-4,int(ctime1));
}
}
void updatemarker() { /////////////////////////////////////////////////////////////////// update current marker
slcd(0,1,1," ");
slcd(6,1,1," ");
slcd(11,1,1," ");
if (!LOCK) {
if (swmode==0) slcd(6,1,1,">");
if (swmode==1) slcd(11,1,1,">");
if (swmode==2) slcd(0,1,1,">");
}
}
void updatespeed() { ///////////////////////////////////////////////////////////////////////// update fan speed
slcd(1,0,5," ");
if (fanstate0) {
if (MS<stop0) {
slcd(7,0,-4,"CAT");
} else {
if (bstate0) {
ilcd(1,0,2, (((long)btime0*60000)-(MS-(long)b0ts))/1000/60+1);
} else slcd(7,0,1," ");
ilcd(7,0,-4,round(rpm0/5.0)*5);
}
}
else slcd(7,0,-4,"OFF");
if (fanstate1) {
if (MS<stop1) {
slcd(12,0,-4,"CAT");
} else {
if (bstate1) {
ilcd(4,0,2, (((long)btime1*60000)-(MS-(long)b1ts))/1000/60+1);
} else slcd(12,0,1," ");
ilcd(12,0,-4,round(rpm1/5.0)*5);
}
}
else slcd(12,0,-4,"OFF");
}
void serinfo() { /////////////////////////////////////////////////////////////////////////// serial info output
SX(fanstate0);SX(":");SX((int)(v0));SX(":");SX((int)(b0));SX(":");
SX(fanstate1);SX(":");SX((int)(v1));SX(":");SX((int)(b1));SX(":");
SX(rpm0);SX(":");SX(rpm1);SX(":");SX(r0);SX(":");SX(r1);SX(":");
SX(bstate0);SX(":");SX(bstate1);SX(":");SX(btime0);SX(":");SX(btime1);SX(":");
SX(catch0);SX(":");SX(catch1);SX(":");SX(ctime0);SX(":");SX(ctime1);SXN("");
}
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 updatePWM() { ///////////////////////////////////////////////////////////////////// update PWM (fan speed)
if (v0<FANMIN) v0=FANMIN;if (v0>FANMAX) v0=FANMAX;
if (v1<FANMIN) v1=FANMIN;if (v1>FANMAX) v1=FANMAX;
if (b0<FANMIN) b0=FANMIN;if (b0>FANMAX) b0=FANMAX;
if (b1<FANMIN) b1=FANMIN;if (b1>FANMAX) b1=FANMAX;
double v;
if (fanstate0) {
if (MS<stop0) {
OCR1A=0;
} else {
if (bstate0) {
v=b0/(FANMAX/320.0)+r0;if (v<0) v=0;if (v>320) v=320;
OCR1A=v;
} else {
v=v0/(FANMAX/320.0)+r0;if (v<0) v=0;if (v>320) v=320;
OCR1A=v;
}
}
} else OCR1A=0;
if (fanstate1) {
if (MS<stop1) {
OCR1B=0;
} else {
if (bstate1) {
v=b1/(FANMAX/320.0)+r1;if (v<0) v=0;if (v>320) v=320;
OCR1B=v;
} else {
v=v1/(FANMAX/320.0)+r1;if (v<0) v=0;if (v>320) v=320;
OCR1B=v;
}
}
} else OCR1B=0;
}
void rpmint0() {;rpmcount0++;} ///////////////////////////////////////////////////////////////// rpm interrupts
void rpmint1() {;rpmcount1++;}
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);
}
String sstr(String data, char separator, int index) { ///////////////////////////////// get seperated substring
int found=0;
int si[]={0,-1};
int mi=data.length()-1;
for (int i=0; i<=mi && found<=index; i++) {
if (data.charAt(i) == separator || i == mi) {
found++;si[0]=si[1]+1;si[1]=(i==mi) ? i+1 : i;
}
}
return found > index ? data.substring(si[0], si[1]) : "";
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////// END
Code: Alles auswählen
/////////////////////////////////////////////////////////////////////////////// Stir Control (mwx'2019, v1.2.4)
#include <EEPROM.h>
#include <LiquidCrystal_I2C.h>
#define SX Serial.print
#define SXN Serial.println
#define MS (long)millis()
int SPEEDINC = 50; // speed increment
int FANMIN = 200; // fan minimum speed
int FANMAX = 1000; // fan maximum speed
int RINTERVAL = 3000; // regulation interval
int RDELAY = 2000; // regulation delay on changes
int CATCHSTOP = 20000; // catch stop period
int PWM0 = 9; // PWM pin for 1. fan
int PWM1 = 10; // PWM pin for 2. fan
int I0 = 2; // interrupt for 1. fan rpm signal
int I1 = 3; // interrupt for 2. fan rpm signal
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 SAVETAG = 1004; // save tag
LiquidCrystal_I2C lcd(0x27,16,2); // LCD display (connect to SDA/SCL)
int v0,b0,r0,v1,b1,r1,r,fanstate0,fanstate1; // speed and regulation
long rpmcount0,rpmcount1; // rpm counter
double rpm0,rpm1; // rpm
long speedts,dt,rts,swts,bts,ox,savets,catchts0,catchts1,stop0,stop1,b0ts,b1ts; // timing
int bdelay,bprocess,enclast,encval,swmode; // button processing
char form[8],out[32],M[8];String str; // string buffer
int OK,SAVE,LOCK,bstate0,bstate1,btime0,btime1,catch0,catch1,ctime0,ctime1,mode;
void setup() { ////////////////////////////////////////////////////////////////////////////////////////// SETUP
rpmcount0=0;rpmcount1=0;rpm0=0;rpm1=0;bprocess=0;speedts=0;r0=0;r1=0;swmode=2;
Serial.begin(9600); // start serial
lcd.init();lcd.backlight();lcd.clear(); // initialize lcd
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) // non-inverted PWM on ch. A
| _BV(COM1B1) // same on ch; B
| _BV(WGM11); // mode 10: ph. correct PWM, TOP=ICR1
TCCR1B = _BV(WGM13) // ditto
| _BV(CS10); // prescaler=1
ICR1 = 320; // TOP=320
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;
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);
}
pinMode(PWM0,OUTPUT);pinMode(PWM1,OUTPUT); // set pin modes
pinMode(CLK,INPUT);pinMode(DT,INPUT);pinMode(SW,INPUT);
enclast=digitalRead(CLK); // get encoder state
fanstate0=0;fanstate1=0;OCR1A=0;OCR1B=0; // turn fans off
rts=MS;swts=MS;bts=MS;savets=MS;catchts0=MS;catchts1=MS;stop0=MS;stop1=MS; // set timer
bstate0=0;bstate1=0;mode=0;updatelcd();updatespeed();updatemarker();LOCK=0; // set initial states
}
void loop() { //////////////////////////////////////////////////////////////////////////////////////////// LOOP
if (SAVE>0 && MS-savets>60000) {;save();SAVE=0;savets=MS;} ////////////////////////// save settings if needed
if (catch0 && MS-catchts0>(long)ctime0*60000) { ////////////////////////////////////// check catch fish state
catchts0=MS;stop0=MS+CATCHSTOP;
updatePWM();
}
if (catch1 && MS-catchts1>(long)ctime1*60000) {
catchts1=MS;stop1=MS+CATCHSTOP;
updatePWM();
}
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 (Serial.available() > 0) { ////////////////////////////////////////////////////////// serial communication
str=Serial.readString();OK=0;
if (str=="info") {;serinfo();OK=1;} // info
if (str.substring(0,5)=="speed") { // speed <fan0> <fan1>
v0=sstr(str,':',1).toInt();
v1=sstr(str,':',2).toInt();
updatePWM();r0=0;r1=0;rts=MS+RDELAY;
SAVE++;OK=1;updatelcd();serinfo();
}
if (str.substring(0,6)=="bspeed") { // bspeed <fan0> <fan1>
b0=sstr(str,':',1).toInt();
b1=sstr(str,':',2).toInt();
updatePWM();r0=0;r1=0;rts=MS+RDELAY;
SAVE++;OK=1;updatelcd();updatespeed();serinfo();
}
if (str.substring(0,2)=="on") { // on <fan0> <fan1> (value: 0 or 1)
if (sstr(str,':',1).toInt()==1) {;fanstate0=1;r0=0;} else fanstate0=0;
if (sstr(str,':',2).toInt()==1) {;fanstate1=1;r1=0;} else fanstate1=0;
updatePWM();rts=MS+RDELAY;
SAVE++;OK=1;updatelcd();updatespeed();serinfo();
}
if (str.substring(0,5)=="boost") { // boost <fan0> <fan1> (value: 0 or 1)
if (sstr(str,':',1).toInt()==1) {;rts=MS+RDELAY;bstate0=1;b0ts=MS;} else {;bstate0=0;}
if (sstr(str,':',2).toInt()==1) {;rts=MS+RDELAY;bstate1=1;b1ts=MS;} else {;bstate1=0;}
SAVE++;OK=1;updatelcd();updatespeed();serinfo();
}
if (str.substring(0,5)=="catch") { // catch <fan0> <fan1> (value: 0 or 1)
if (sstr(str,':',1).toInt()==1) {;catch0=1;catchts0=MS;} else {;catch0=0;}
if (sstr(str,':',2).toInt()==1) {;catch1=1;catchts1=MS;} else {;catch1=0;}
SAVE++;OK=1;updatelcd();updatespeed();serinfo();
}
if (str.substring(0,5)=="btime") { // btime <fan0> <fan1> (value: 0-60)
btime0=sstr(str,':',1).toInt();if (btime0<0) btime0=0;if (btime0>60) btime0=60;
btime1=sstr(str,':',2).toInt();if (btime1<0) btime1=0;if (btime1>60) btime1=60;
SAVE++;OK=1;updatelcd();updatespeed();serinfo();
}
if (str.substring(0,5)=="ctime") { // ctime <fan0> <fan1> (value: 60-240)
ctime0=sstr(str,':',1).toInt();if (ctime0<60) ctime0=60;if (ctime0>240) ctime0=240;
ctime1=sstr(str,':',2).toInt();if (ctime1<60) ctime1=60;if (ctime1>240) ctime1=240;
SAVE++;OK=1;updatelcd();updatespeed();serinfo();
}
if (!OK) SXN("ERROR");
}
if (MS-rts>RINTERVAL) { ////////////////////////////////////////////////////////////////////////// regulation
rpm0=rpmcount0/2/((MS-speedts)/1000.0)*60.0;
rpm1=rpmcount1/2/((MS-speedts)/1000.0)*60.0;
speedts=MS;rpmcount0=0;rpmcount1=0;
if (abs(v0-rpm0)>8) {
ox=1;if (abs(v0-rpm0)>20) ox=3;if (abs(v0-rpm0)>50) ox=5;
if (bstate0) r=b0; else r=v0;
if (r>rpm0) {;r0+=ox;if (r0>40) r0=40;}
if (r<rpm0) {;r0-=ox;if (r0<-40) r0=-40;}
}
if (abs(v1-rpm1)>8) {
ox=1;if (abs(v1-rpm1)>20) ox=3;if (abs(v1-rpm1)>50) ox=5;
if (bstate1) r=b1; else r=v1;
if (r>rpm1) {;r1+=ox;if (r1>40) r1=40;}
if (r<rpm1) {;r1-=ox;if (r1<-40) r1=-40;}
}
if (!fanstate0) r0=0;
if (!fanstate1) r1=0;
updatePWM();updatespeed();rts=MS;
}
bdelay=0; //////////////////////////////////////////////////////////////////////////////////// process switch
if (!bprocess) {
while (!digitalRead(SW)){
bdelay++;
delay(25);
bprocess=1;
if (bdelay>20) break;
}
}
if (bdelay>0 && MS-bts>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;r0=0;updatePWM();}
else {;fanstate0=0;}
updatespeed();
}
if (swmode==1 && mode==0 && !LOCK) { // fan 1 on/off
if (fanstate1==0) {;rts=MS+RDELAY;fanstate1=1;r1=0;updatePWM();}
else {;fanstate1=0;}
updatespeed();
}
if (swmode==0 && mode==1 && !LOCK) { // boost 0 on/off
if (bstate0==0) {
rts=MS+RDELAY;bstate0=1;b0ts=MS;fanstate0=1;r0=0;updatePWM();
} else {;bstate0=0;}
updatespeed();
}
if (swmode==1 && mode==1 && !LOCK) { // boost 1 on/off
if (bstate1==0) {
rts=MS+RDELAY;bstate1=1;b1ts=MS;fanstate1=1;r1=0;updatePWM();
} else {;bstate1=0;}
updatespeed();
}
if (swmode==2) { // lock/unlock
if (LOCK==0) LOCK=1;
else LOCK=0;
updatemarker();
}
bdelay=0;
} else if (bdelay>0 && bdelay<20 && !LOCK) { // short button press: switch menu -> fan 0 -> fan 1
swmode++;if (swmode>2) swmode=0;
updatemarker();
bdelay=0;
}
bts=MS;
}
if (digitalRead(SW)) bprocess=0;
encval = digitalRead(CLK); ////////////////////////////////////////////////////////////////// process encoder
if (encval != enclast && !LOCK) {
if(!encval){
if (digitalRead(DT) != encval) { // cw
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==2) mode++;
} else { // ccw
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==2) mode--;
}
if (swmode==0 && mode==0) {;updatePWM();r0=0;rts=MS+RDELAY;} // apply speed change 0
if (swmode==1 && mode==0) {;updatePWM();r1=0;rts=MS+RDELAY;} // apply speed change 1
if (swmode==0 && mode==1) {;updatePWM();r0=0;rts=MS+RDELAY;} // apply boost speed change 0
if (swmode==1 && mode==1) {;updatePWM();r1=0;rts=MS+RDELAY;} // apply boost speed change 1
if (swmode==0 && mode==2) {;if (btime0<0) btime0=0;if (btime0>60) btime0=60;} // check boost time 0
if (swmode==1 && mode==2) {;if (btime1<0) btime1=0;if (btime1>60) btime1=60;} // check boost time 1
if (swmode==0 && mode==3) {;if (catch0<0) catch0=1;if (catch0>1) catch0=0;catchts0=MS;} // check catch 0
if (swmode==1 && mode==3) {;if (catch1<0) catch1=0;if (catch1>1) catch1=0;catchts1=MS;} // check catch 1
if (swmode==0 && mode==4) {;if (ctime0<60) ctime0=60;if (ctime0>240) ctime0=240;} // check boost time 0
if (swmode==1 && mode==4) {;if (ctime1<60) ctime1=60;if (ctime1>240) ctime1=240;} // check boost time 1
if (swmode==2) {;if (mode<0) mode=4;if (mode>4) mode=0;} // check menu mode
SAVE++;updatelcd();delay(50);
}
}
enclast=encval;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////// SUPPORT
void updatelcd() { ///////////////////////////////////////////////////////////////////////////////// update LCD
if (mode==0) {
slcd(1,1,5,"SPEED");
ilcd(7,1,-4,int(v0));
ilcd(12,1,-4,int(v1));
}
if (mode==1) {
slcd(1,1,5,"BOOST");
ilcd(7,1,-4,int(b0));
ilcd(12,1,-4,int(b1));
}
if (mode==2) {
slcd(1,1,5,"BTIME");
ilcd(7,1,-4,int(btime0));ilcd(12,1,-4,int(btime1));
}
if (mode==3) {
slcd(1,1,5,"CATCH");
if (catch0==0) slcd(7,1,-4,"OFF");
else slcd(7,1,-3,"ON");
if (catch1==0) slcd(12,1,-4,"OFF");
else slcd(12,1,-3,"ON");
}
if (mode==4) {
slcd(1,1,5,"CTIME");
ilcd(7,1,-4,int(ctime0));ilcd(12,1,-4,int(ctime1));
}
}
void updatemarker() { /////////////////////////////////////////////////////////////////// update current marker
slcd(0,1,1," ");
slcd(6,1,1," ");
slcd(11,1,1," ");
if (!LOCK) {
if (swmode==0) slcd(6,1,1,">");
if (swmode==1) slcd(11,1,1,">");
if (swmode==2) slcd(0,1,1,">");
}
}
void updatespeed() { ///////////////////////////////////////////////////////////////////////// update fan speed
slcd(1,0,5," ");
if (fanstate0) {
if (MS<stop0) {
slcd(7,0,-4,"CAT");
} else {
if (bstate0) {
ilcd(1,0,2, (((long)btime0*60000)-(MS-(long)b0ts))/1000/60+1);
} else slcd(7,0,1," ");
ilcd(7,0,-4,round(rpm0/5.0)*5);
}
}
else slcd(7,0,-4,"OFF");
if (fanstate1) {
if (MS<stop1) {
slcd(12,0,-4,"CAT");
} else {
if (bstate1) {
ilcd(4,0,2, (((long)btime1*60000)-(MS-(long)b1ts))/1000/60+1);
} else slcd(12,0,1," ");
ilcd(12,0,-4,round(rpm1/5.0)*5);
}
}
else slcd(12,0,-4,"OFF");
}
void serinfo() { /////////////////////////////////////////////////////////////////////////// serial info output
SX(fanstate0);SX(":");SX((int)(v0));SX(":");SX((int)(b0));SX(":");
SX(fanstate1);SX(":");SX((int)(v1));SX(":");SX((int)(b1));SX(":");
SX(rpm0);SX(":");SX(rpm1);SX(":");SX(r0);SX(":");SX(r1);SX(":");
SX(bstate0);SX(":");SX(bstate1);SX(":");SX(btime0);SX(":");SX(btime1);SX(":");
SX(catch0);SX(":");SX(catch1);SX(":");SX(ctime0);SX(":");SX(ctime1);SXN("");
}
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 updatePWM() { ///////////////////////////////////////////////////////////////////// update PWM (fan speed)
if (v0<FANMIN) v0=FANMIN;if (v0>FANMAX) v0=FANMAX;
if (v1<FANMIN) v1=FANMIN;if (v1>FANMAX) v1=FANMAX;
if (b0<FANMIN) b0=FANMIN;if (b0>FANMAX) b0=FANMAX;
if (b1<FANMIN) b1=FANMIN;if (b1>FANMAX) b1=FANMAX;
double v;
if (fanstate0) {
if (MS<stop0) {
OCR1A=0;
} else {
if (bstate0) {
v=b0/(FANMAX/320.0)+r0;if (v<0) v=0;if (v>320) v=320;
OCR1A=v;
} else {
v=v0/(FANMAX/320.0)+r0;if (v<0) v=0;if (v>320) v=320;
OCR1A=v;
}
}
} else OCR1A=0;
if (fanstate1) {
if (MS<stop1) {
OCR1B=0;
} else {
if (bstate1) {
v=b1/(FANMAX/320.0)+r1;if (v<0) v=0;if (v>320) v=320;
OCR1B=v;
} else {
v=v1/(FANMAX/320.0)+r1;if (v<0) v=0;if (v>320) v=320;
OCR1B=v;
}
}
} else OCR1B=0;
}
void rpmint0() {;rpmcount0++;} ///////////////////////////////////////////////////////////////// rpm interrupts
void rpmint1() {;rpmcount1++;}
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);
}
String sstr(String data, char separator, int index) { ///////////////////////////////// get saperated substring
int found=0;
int si[]={0,-1};
int mi=data.length()-1;
for (int i=0; i<=mi && found<=index; i++) {
if (data.charAt(i) == separator || i == mi) {
found++;si[0]=si[1]+1;si[1]=(i==mi) ? i+1 : i;
}
}
return found > index ? data.substring(si[0], si[1]) : "";
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////// END
Sind das ESP8266 Boards (z.B. D1 Mini)? Soweit ich mich erinnere und die Doku richtig verstanden habe, können die leider nur PWM mit maximal 1 kHz.DerDerDasBierBraut hat geschrieben: ↑Dienstag 19. Februar 2019, 13:42 Ist auf dem Wemos auch was zu beachten?
Davon habe ich noch sehr viele hier. Wenn es geht würde ich lieber einen davon verwenden anstatt einen Uno zusätzlich zu kaufen.
also so für Uno?mwx hat geschrieben: ↑Dienstag 19. Februar 2019, 12:46 Noch ein Hinweis für die die einen Arduino UNO verwenden möchten: Der hat auf Pin 0 und 1 keine Interrupts sondern nur auf Pin 2 und 3 also bitte dort anschließen. Im Quelltext müssen dann die Interrupts noch auf 0 und 1 geändert werden. Das ist verwirrend weil genau umgekehrt :)
Ok, dann geht es nicht. Wenn Du einen UNO nimmst hast Du auch den Vorteil das Du den direkt mit 12V füttern kannst. Du brauchst dann keinen zusätzlichen Step-Down oder ähnliches.
ja genau so.flensdorfer hat geschrieben: ↑Dienstag 19. Februar 2019, 14:19 also so für Uno?
[code
int I0 = 0; // interrupt for 1. fan rpm signal
int I1 = 1; // interrupt for 2. fan rpm signal
[/code]
ein Link von Frudel:https://www.ebay.de/itm/5-X-POWER-NEODY ... 9#shpCntIdflensdorfer hat geschrieben: ↑Dienstag 19. Februar 2019, 10:45 Günstige Bezugsquelle für die Magnete? magnet-shop.net nimmt den Warenwert nochmal als Versandkosten... Oder hat jemand ein paar 20x10x5 rumliegen?
bis zu welcher Drehzahl werden die denn in der Praxis tatsächlich eingesetzt?flensdorfer hat geschrieben: ↑Dienstag 19. Februar 2019, 14:43 Macht es u.U. mehr sinn, den 120er zu nehmen? Der dreht bis 2200rpm, während der 140er "nur" bis 1600rpm geht. Oder bekommt man dann die Magnete nicht vernünftig untergebracht?.
der ebay-Link war gut, mir wurde noch ein 5€ Gutschein von ebay angezeigt. Habe mir dann gleich mal welche bestellt.daleipi hat geschrieben: ↑Dienstag 19. Februar 2019, 18:36ein Link von Frudel:https://www.ebay.de/itm/5-X-POWER-NEODY ... 9#shpCntIdflensdorfer hat geschrieben: ↑Dienstag 19. Februar 2019, 10:45 Günstige Bezugsquelle für die Magnete?
Ich habe hier bestellt.daleipi hat geschrieben: ↑Dienstag 19. Februar 2019, 18:36ein Link von Frudel:https://www.ebay.de/itm/5-X-POWER-NEODY ... 9#shpCntIdflensdorfer hat geschrieben: ↑Dienstag 19. Februar 2019, 10:45 Günstige Bezugsquelle für die Magnete? magnet-shop.net nimmt den Warenwert nochmal als Versandkosten... Oder hat jemand ein paar 20x10x5 rumliegen?
ich hab meine von da: https://www.magnetmax.de/Neodym-Quaderm ... g::66.html