• New hardware:
    128x64 digole display, with the reflective backing removed and replaced with EL panel. The backlight draws about 250 mils, so it needs to be switched using a mosfet (in this case, a dangling mosfet on a standalone breakout board with tape wrapped around it ).

    Previously, the 5.6v operating voltage was supplied by an external PSU, and the 3.3v was supplied with a buck converter, which was excessive considering the low nominal load.

    Now, the 5.6v operating voltage is stepped down from 12v from the 12v 10A supply that powers low voltage stuff in my room, inside the control box, using a 5A buck converter (from ebay - one of the ones that says to use heatsinks if you go over 2.5A. I had to heatsink both the chip and the underside of the board below it to keep the temperatures in my comfort zone. But hell, it was $2.50!), and I replaced the 3.3v converter with an LDO regulator.

    Electronics now contained (mostly) within a blue bin turned upside down (with wire holes in it, ofc).

    Finally, I added an 8 KB I2C eeprom module, which I use to save presets to.

    New software:

    
    function onInit() {
    	rh=-1;
    	t=-1;
    	pr=0;
    	usrmsg="";
    	statusview=1;
    	menustate=0;
    	menuopt=0;
    	inval="";
    	msg="";
        setBusyIndicator(A13);
    	fargosturl="http://192.168.2.163/fargostatus.php";
    	fargourl="http://192.168.2.14/api/relay/";
    	fargo=new Uint8Array(8);
    	colors="BLUECOOLWARMYELLPINK";
    	gw=new Uint8Array([7,9,9,7,7]);
    	fargostrs="Colored,White,Wizard,Tentacle,Desk,Micro,Fan, ";
    	ledstate=new Float32Array([0.0,0.0,0.0,0.0,0.0]);
    	//presets=[new Float32Array([0.0,0.0,0.0,0.0,0.0]),new Float32Array([0.9,1,0.6,0,0]),new Float32Array([0,0.6,1,0.8,0.4]),new Float32Array([0.5,0.5,0.5,0.5,0.5])];
    	//prenames=["OFF","COLD\nWHIT","VERY\nWARM","HALF\nHALF"];
    	
    	ledpins=[C6,C7,C8,A8,C9];
    	upled();
    	I2C2.setup({scl:B10,sda:B11});
    	kp=require("KeyPad").connect([C2,C3,A0,A1],[C1,C0,C15,C12,B12], function(e) {onKey("AB#*123U456D789CL0RE"[e]);});
    	bmp=require("BMP085").connect(I2C2,3);
    	e=require("DHT22").connect(A6);
    	require("Font8x12").add(Graphics);
    	rom=require("AT24").connect(I2C2,32,64);
    	eth=require("WIZnet").connect();
    	eth.setIP();
    	setTimeout("var s=require('http').createServer(function (req, res) {var par=url.parse(req.url,true);var q=par.query; var nam=par.pathname; nam=nam.split('/');nam=nam[1];var rd=procreq(nam,q);res.writeHead(rd.code,{'Content-Type': 'text/plain'}); res.write(rd.body);res.end();}).listen(80);",15000);
    	setInterval("bmp.getPressure(function(b){pr=b.pressure;});e.read(function(a){if(a.rh != -1) {rh=a.rh;t=a.temp;}});",30000);
    	setTimeout("setInterval(function(){uplcd();},30000);",15000);
    	setTimeout("setInterval('getfargostatus();',30000);",20000);
    	setInterval("delete onInit",500); 
    	g = require("DigoleBuf").connect(I2C2,128,64);
    	g.clear();
    	g.setFont8x12();
    	g.drawString("LCD OK",0,0);
    	g.flip();
    	g.setContrast(0x26);
    	g.bktim=0;
        g.backlighton = function(tim_) {
    		digitalWrite(B0,1);
    	   	var tim=(tim_) ? tim_ :5000;
    		if (this.bktim) {
    			try {
    				clearTimeout(this.bktim);
    			}
    			catch (err) {
    				this.bktim=0;
    			}
    			this.bktim=0;
    		}
    		this.bktim=setTimeout("digitalWrite(B0,0);g.bktim=0;",tim);
    	};
    	g.backlighton();
    	presets=[new Float32Array([0.0,0.0,0.0,0.0,0.0])];
    	prenames=["OFF"];
    	var i=1;
    	while (rom.reads(32*(i-1),1) != "\xFF") {
    		 prenames[i]=rom.reads(32*(i-1),12);
    		 var temp=rom.read(32*(i-1)+16,5);
    		 presets[i]=new Float32Array([temp[0]/100.0,temp[1]/100.0,temp[2]/100.0,temp[3]/100.0,temp[4]/100.0]);
    		 i++;
    	}
    	menu=[0,4,presets.length-1];
    }
    
    function procreq(path,query) {
    	var rd={};
    	rd.code=404;
    	rd.body="";
    	if (path=="status.json") {
    		rd.code=200;
    		var r='{"lamp":{';
    		for (var i=0;i<5;i++) {
    			r+='"'+colors.substr(i*4,4)+'":'+ledstate[i].toFixed(2);
    			if (i<4) {r+=",";}
    		}
    		r+='},\n"sensors":{"rh":'+rh.toFixed(1)+',"temp":'+t.toFixed(1)+',"pressure":'+pr.toFixed(2)+'}}';
    		rd.body=r;
    	} else if (path=="lamp.cmd") {
    		rd.code=200;
    		rd.body="Command applied";
    		if (query.BLUE != undefined) {
    			ledstate[0]=E.clip(query.BLUE,0,1);
    		} else {ledstate[0]=0;}
    		if (query.COOL != undefined) {
    			ledstate[1]=E.clip(query.COOL,0,1);
    		} else {ledstate[1]=0;}
    		if (query.WARM != undefined) {
    			ledstate[2]=E.clip(query.WARM,0,1);
    		} else {ledstate[2]=0;}
    		if (query.YELL != undefined) {
    			ledstate[3]=E.clip(query.YELL,0,1);
    		} else {ledstate[3]=0;}
    		if (query.PINK != undefined) {
    			ledstate[4]=E.clip(query.PINK,0,1);
    		} else {ledstate[4]=0;}
    		setTimeout("uplcd(); upled();",100);
    	} else if (path=="code.run") {
    		if (query.code) {
    			rd.code=200;
    			rd.body=eval(query.code);
    		} else {
    			rd.code=400;
    			rd.body="400 Bad Request: No code supplied!";
    		}
    	} else if (path=="usrmsg.cmd") {
    		if (query.msg && query.msg.length > 1) {
    			rd.code=200;
    			usrmsg=query.msg;
    			rd.body="Message set: "+query.msg;
    			menustate=10;
    			setTimeout("uplcd();",100);
    		} else {rd.code=400; rd.body="400 Bad Request: No message supplied";}
    	} else if (path=="" || path=="index.html") {rd.code=403; rd.body="403 Forbidden";}
    	return rd;
    }
    
    function getLedStr() {
    	var rtnstr="";
    	for (var it=0;it < 5; it++ ) {
    		rtnstr+=String.fromCharCode(Math.round(ledstate[it]*100));
    	}
    	return rtnstr;
    }
    
    function getT9() {
    	if (t9num==-1) {
    		return "";
    	} 
      var bas=58;
      var maxmen=4;
      if (t9num==9 || t9num==7) {
        maxmen++;
      }
      if (t9num>7) {
        bas+=1;
      }
      if (t9num===0) {
        if (t9cnt==1) {
          return " ";
        } else {
          return "0";
        }
      }
      if (t9cnt==maxmen) {
        return String.fromCharCode(t9num+48);
      } else {
        return String.fromCharCode(t9num*3+bas+t9cnt);
      }
      return "";
    }
    
    function onKey(k){
    	msg="";
    	if (menustate==5) {
    		if (k=="L" && t9str.length > 0) {
    			t9str=t9str.substr(0,t9str.length-1);
    			t9cnt=0;
    			t9num=-1;
    			if (t9watch!=-1) {
    	    		clearTimeout(t9watch);
    	    		t9watch=-1;
    	    	}
    		} else if ( k=="C" ) {
    			menustate=0;
    			inval="";
    			menuopt=0;
    			t9str="";
    			t9cnt=0;
    			t9num=-1;
    			if (t9watch!=-1) {
    	    		clearTimeout(t9watch);
    	    		t9watch=-1;
    	    	}
    		} else if ( k =="E" && t9str != "") {
    			prenames[prenames.length]=t9str;
    			presets[presets.length]=new Float32Array(ledstate);
    			var outstr=t9str;
    			while (outstr.length <= 15) {
    				outstr+=" ";
    			}
    			outstr+=getLedStr();
    			while (outstr.length <= 31) {
    				outstr+=" ";
    			}
    			rom.writes((presets.length-2)*32,outstr);
    			menu=[0,4,presets.length-1];
    			msg="Saved";
    			menustate=0;
    			menuopt=0;
    			t9str="";
    			t9cnt=0;
    			t9num=-1;
    			if (t9watch!=-1) {
    	    		clearTimeout(t9watch);
    	    		t9watch=-1;
    	    	}
    		} else  if (t9str.length < 12) {
    			var a=parseInt(k);
     			if (a != NaN) {
        			if (t9watch!=-1) {
    		    		clearTimeout(t9watch);
    		    		t9watch=-1;
    		    	}
    		    	if (t9cnt==0) {
    		    		t9num=a;
    		    		t9cnt=1;
    		    	} else if (t9num==1) {
    		    		t9str+="1";
    		    		t9num=-1;
    		    	t9cnt=0;
    		    	} else if (t9num==a) {
    		    		if (((t9num==9 || t9num==7) && t9cnt==5) || (t9num==0 && t9cnt==2) || (t9num!=9 && t9num!=7 && t9num!=0 && t9cnt==4) ) {
    		        	t9cnt=1;
    		    	} else {
    		        	t9cnt++;
    		      	}
    		    } else {
    		    	t9str+=getT9();
    		    	t9num=a;
    		    	t9cnt=1;
    		    }
    		    t9watch=setTimeout("t9str+=getT9();t9num=-1;t9cnt=0;t9watch=-1;;uplcd();",2000);
    		  }
    		}
    	} else if (k=="*"){
    		if (menustate>=4){
    			menustate=0;
    		} else {
    			menustate++;
    		}
    		menuopt=0;
    		inval="";
    	} else if ((menustate==2 || menustate == 1) && k=="#"){
    		if (menuopt==0 || menustate ==1) { 
    			menustate=5;
    			t9cnt=0;
    			t9num=-1;
    			t9str="";
    		} else {
    			presets[menuopt]=new Float32Array(ledstate);
    			rom.writes((menuopt-1)*32+16,getLedStr());
    			msg="Saved";
    			menuopt=0;
    			menustate=0;
    		}
    
    	} else if (k=="E" && menustate) {
    		if (menustate==1 && inval) {
    			var v=E.clip(parseInt(inval),0,100);
    			v=v/100;
    			ledstate[menuopt]=v;
    			inval="";
    			upled();
    		} else if (menustate==2) {
    			ledstate=new Float32Array(presets[menuopt]);
    			menuopt=0;
    			menustate=0;
    			upled();
    		} else if (menustate==3) {
    			var ex=fargo[menuopt];
    			setFargo(menuopt,!ex);
    		}
    	} else if ((k=="L"||k=="R") && (menustate==1||menustate==2)) {
    		if (k=="R") {
    			if (menuopt>=menu[menustate]) {
    				menuopt=0;
    			} else {
    				menuopt++;
    			}
    		} else {
    			if (menuopt==0) {
    				menuopt=menu[menustate];
    			} else {
    				menuopt--;
    			}
    		}
    		inval="";
    	} else if ((k=="U"||k=="D") && menustate==1) {
    		if (k=="U") {
    			ledstate[menuopt]=E.clip(100*ledstate[menuopt]+4,0,100)/100;
    		} else {
    			ledstate[menuopt]=E.clip(100*ledstate[menuopt]-4,0,100)/100;
    		}
    		inval="";
    		upled();
    	} else if (menustate==3) {
    		if (k=="D") {
    			menuopt=(menuopt&4)|((menuopt+1)&3);
    		} else if (k=="U") {
    			menuopt=(menuopt&4)|((menuopt-1)&3);
    		} else if (k=="R"||k=="L") {
    			menuopt=menuopt^4;
    		}
    	} else if (k=="A") {
    		ledstate=new Float32Array([0,0,0,0,0]);
    		upled();
    		uplcd();
    	} else if ( k=="C" ) {
    		menustate=0;
    		inval="";
    		menuopt=0;
    	} else if (menustate==1) {
    		if (inval.length < 3) {
    			inval=inval+k;
    		} else {
    			inval="";
    		}
    	}
    	uplcd();
    	g.backlighton();
    }
    
    function getfargostatus() {
    	var fargost="";
    	require("http").get(fargosturl, function(res) {
    		res.on('data',function (data) {fargost+=data;});
          res.on('close',function() {var tfs=JSON.parse(fargost); vtfs=tfs; for (var i=0;i<8;i++) { fargo[i]=tfs.relaystate[i].state;} if(menustate==3){uplcd();}});
    	});
    }
    function setFargo(relay,state) {
    	var postfix = (state) ? "/on":"/off";
      require("http").get(fargourl+(relay+1).toString()+postfix, function(res) {
        res.on('close',function () {
          if(this.code!=200) {
            fargo[relay]=state;
            uplcd();
          }
        });
      });
    }
    
    function textWrap(str,len) {
    	var l=str.length;
    	if (l < len) { return str; }
    	else {
    		var o="";
            for (var i=0; i < l; i+=len) 
            {
    			if (i+len > l) {
    				o+=str.substring(i,l);
    			} else { 
    				o+=str.substr(i,len)+"\n";
    			}
    		}
    		return o;
    	}
    }
    
    
    function uplcd() {
    	g.clear();
        var tpr=0.000295333727*pr;
    	g.drawString(t.toFixed(1)+" C "+rh.toFixed(1)+"% "+tpr.toFixed(1),0,0);
    	if (menustate < 3 || menustate==5) {
    		usrmsg="";
    		var vals=new Float32Array(ledstate);
    		if (menustate==2){
    			vals=new Float32Array(presets[menuopt]);
    		} else if (menustate==1 && inval) {
    			vals[menuopt]=(parseInt(inval)/100);
    		}
    		var x=3;
    		for (var i=0;i<5;i++) {
    			var nx=x+gw[i];
    			g.drawRect(x,15,nx,47);
    			g.fillRect(x,(47-ledstate[i]*32),nx,47);
    			if (vals[i] != ledstate[i]) {
    				if (vals[i] > ledstate[i]) {
    					g.fillRect(x+1,(47-vals[i]*32),nx-1,48-vals[i]*32);
    				} else {
    					g.setColor(0);
    					g.fillRect(x+1,(47-vals[i]*32),nx-1,46-vals[i]*32);
    					g.setColor(1);
    				}
    			}
    			x=nx+4;
    		}
    		g.drawString("B",4,50);
    		g.drawString("C",16,50);
    		g.drawString("W",29,50);
    		g.drawString("Y",41,50);
    		g.drawString("P",57,50);
    
    		for (var j=0;j<8;j++) {
    			if (fargo[j]==0) {
    				g.drawRect(122,15+j*6,126,19+j*6);
    			} else {
    				g.fillRect(122,15+j*6,126,19+j*6);
    			}
    		}
    	} else if (menustate == 3) {
          	var fst=fargostrs.split(',');
    		g.setFontBitmap();
    		for (var j=0;j<8;j++) {
    			if (fargo[j]==0) {
    				g.drawRect(4+(j>>2)*64,17+(j&3)*12,11+(j>>2)*64,22+(j&3)*12);
    			} else {
    				g.fillRect(4+(j>>2)*64,17+(j&3)*12,11+(j>>2)*64,22+(j&3)*12);
    			}
    			g.drawString(fst[j],14+(j>>2)*64,18+(j&3)*12);
    		}
    		g.drawRect(2+(menuopt>>2)*64,15+(menuopt&3)*12,61+(menuopt>>2)*64,24+(menuopt&3)*12);
    		g.setFont8x12();
    	} else if (menustate == 10) {
    		if (usrmsg==""){
    			menustate=0;
    			menuopt=0;
    		} else {
    			g.drawString(usrmsg,1,17);
    			g.backlighton(30000);
    		}
    	}
    	if (menustate===0 && msg) {
    		
    		g.drawString(msg,70,17);
    	}else if (menustate==1) {
    		g.drawString(colors.substr(menuopt*4,4),70,17);
    		g.drawString((100*ledstate[menuopt]).toFixed(),80,32);
    		if (inval) {
    			g.drawString(inval,80,46);
    		}
    	} else if (menustate==2 || menustate==5) {
    		var tstr=(menustate==2 ? prenames[menuopt] : t9str);
    		if (menustate==5 && tstr.length < 12 ) {
    			if (getT9() == "" ) {
    				tstr+="_";
    			} else {
    				tstr+=getT9();
    			}
    		}
    		if (tstr.length > 8 ) {
    			g.drawString(tstr,70,17);
    		} else {
    			g.drawString(tstr.substring(0,7),70,17);
     			g.drawString(tstr.substring(8,tstr.length),70,32);
    		}
    	}
    	g.flip();
    }
    
    function upled() {
    	for (var i=0;i<5;i++) {
    		analogWrite(ledpins[i],ledstate[i]);
    	}
    }
    
    
    
About

Avatar for DrAzzy @DrAzzy started