Javascript with Picaxe

eclectic

Moderator
This question appears to follow Distiller's thread

http://www.picaxeforum.co.uk/showthread.php?t=8256

I did an Internet search earlier, and found a page containing these five lines

"DeltaSG= 1.00130346 - 1.34722124E-4 * T + 2.04052596E-6* T^2 -
2.32820948E-9 *T^3
He then calculates DeltaSG at the hydrometer's calibration temp (ct) and at
the hydrometer sample temp (it), and calculates the corrected SG as SG *
DeltaSG(it)/DeltaSG(ct) "


But now, I can't find the page again!
No idea what the T values are measured in (degF, degC or degK).
And, of course, the calculation looks seriously difficult for a Picaxe!

Awaiting Distiller's further input.

e.
 
Last edited:

Distiller

New Member
javascript with picaxe

Below is the extraction of the page source for the "dead" site.

Now dead for me as well. Shortened to fit in "legal" length of posts...hope it still works....


Regards,

Brian



<!doctype html public "-//w3c//dtd html 3.2//en">
<html>


<head>
<meta name="description" content="JavaScript applet temperature corrects hydrometer readings.">
<meta name="keywords" content="homebrew, beer, brewing, hydrometer, specific gravity, plato, balling, brix">



<body text=#000000 bgcolor=#ffffff vlink=#800080 link=#0000ff onLoad="GO_default = document.GO_form.widget.selectedIndex; OnLoad()">

<script language="JavaScript">
<!--

///////////////////////////////////////////////////////////////////////////////

function OnLoad()
{
ParseCookie();
}

///////////////////////////////////////////////////////////////////////////////

function GetSelectValue(select)
{
return select.options[select.selectedIndex].value;
}

function SetSelectValue(select, value)
{
for (var i = 0; i < select.length; i++)
if (select.options.value == value)
select.selectedIndex = i;
}

///////////////////////////////////////////////////////////////////////////////

var cookie;

function GetCookieArg()
{
var arg;
if ((i = cookie.indexOf(',')) < 0)
i = cookie.length;
arg = cookie.substring(0, i);
cookie = cookie.substring(i + 1);
return arg;
}

function ParseCookie()
{
var k0 = document.cookie;
var k, i;

while (k0.length)
{
while (k0.charAt(0) == ' ')
k0 = k0.substring(1);

if ((i = k0.indexOf(';')) < 0)
k = k0, k0 = "";
else
k = k0.substring(0, i), k0 = k0.substring(i + 1);

i = k.indexOf('=');
if (k.substring(0, i) == "hc")
{
cookie = k.substring(i + 1);
DecodeCookie();
}
}
}

function SetCookie()
{
var k = "hc=" + EncodeCookie();

var d = new Date();
d.setYear(d.getYear() + 1);
k += "; expires=" + d.toGMTString();

document.cookie = k;
}

function EncodeCookie()
{
var f = document.SG_form;
return GetSelectValue(f.iru)
+ "," + GetSelectValue(f.itu)
+ "," + GetSelectValue(f.ctu)
+ "," + GetSelectValue(f.cru)
+ "," + escape(f.ct.value);
}

function DecodeCookie()
{
var f = document.SG_form;
SetSelectValue(f.iru, GetCookieArg());
SetSelectValue(f.itu, GetCookieArg());
SetSelectValue(f.ctu, GetCookieArg());
SetSelectValue(f.cru, GetCookieArg());
f.ct.value = unescape(GetCookieArg());
}

///////////////////////////////////////////////////////////////////////////////

function Round(n,d)
{
var m, i;
for (i = 0, m = 1; i < d; i++, m *= 10);
return Math.round(n * m) / m;
}

///////////////////////////////////////////////////////////////////////////////

function StripSpaces(s)
{
for (i = 0; s.charAt(i) == ' '; i++);
return s.substring(i);
}

function ParseInput(s)
{
var q, d = 0, n;
var i = 0;
var t = "", u;

s = StripSpaces(s);

if ((n = s.indexOf('/')) >= 0)
{
u = StripSpaces(s.substring(n + 1));
d = parseFloat(u);
if (u == "" || isNaN(d) || d == 0)
return "";
s = s.substring(0, n);

if ((n = s.indexOf(' ')) >= 0)
t = StripSpaces(s.substring(n + 1)),
s = s.substring(0, n);

if (t == "")
t = s,
s = "";
}

if (t == "" && s == "")
return "";

if (s != "")
{
i = parseFloat(s);
if (isNaN(i))
return "";
}

if (t != "")
{
q = parseFloat(t);
if (isNaN(q))
return "";

i += (i < 0) ? -q / d : q / d;
}

return i;
}

function InputError(i, m)
{
alert(m);
i.focus(); i.select();
return "";
}

function IsError(n)
{
var s = "" + n;
return s.length ? 0 : 1;
}

///////////////////////////////////////////////////////////////////////////////

function ParseTemp(i,u,minf,maxf,minc,maxc,label)
{
var t = ParseInput(i.value);
if (u == "c")
{
if (IsError(t) || t < minc || t > maxc)
return InputError(i, "Please enter " + label + " in the range " + minc + " - " + maxc);
t = t * 1.8 + 32;
}
else
{
if (IsError(t) || t < minf || t > maxf)
return InputError(i, "Please enter " + label + " in the range " + minf + " - " + maxf);
}
return t;
}

///////////////////////////////////////////////////////////////////////////////

function P2SG(p)
{
return 1.00001
+ 3.8661E-3 * p
+ 1.3488E-5 * p * p
+ 4.3074E-8 * p * p * p;
}

function SG2P(sg)
{
return -668.962
+ 1262.45 * sg
- 776.43 * sg * sg
+ 182.94 * sg * sg * sg;
}

function SG60(t)
{
return 1.00130346
- 1.34722124E-4 * t
+ 2.04052596E-6 * t * t
- 2.32820948E-9 * t * t * t;
}

function SG2String(sg)
{
return "" + Round(sg * 1000, 1);
}

function ParseSG(i,u,minsg,maxsg,minp,maxp,label)
{
var sg = parseFloat(i.value);
if (u == "p")
{
if (isNaN(sg) || sg < minp || sg > maxp)
return InputError(i, "Please enter " + label + " in the range " + minp + " - " + maxp);
sg = P2SG(sg);
}
else
{
if (!isNaN(sg))
{
if (sg >= 900)
{
sg /= 1000;
}
else if (sg >= 2 && sg <= 500)
{
sg = 1 + sg / 1000;
i.value = SG2String(sg);
}
}
if (isNaN(sg) || sg < minsg || sg > maxsg)
return InputError(i, "Please enter " + label + " in the range " + SG2String(minsg) + " - " + SG2String(maxsg));
}
return sg;
}

function OutputSG(i,u,sg)
{
if (u == "p")
i.value = Round(SG2P(sg), 2);
else
i.value = SG2String(sg);
}

///////////////////////////////////////////////////////////////////////////////

function FormatFloat(n, digits)
{
var s, m, e, hi, lo, z, elo, d;

if (n == 0)
return "0";

if (n < 0)
n = -n, s = "-";
else
s = "";

lo = 1, e = 0;
for (i = 1; i < digits; i++)
lo *= 10, e++;
hi = lo * 10;

m = n;
while (m < lo) m *= 10, e--;
while (m >= hi) m /= 10, e++;

m = Math.round(m);
if (m >= hi) m /= 10, e++;

elo = -2, z = m;
while (z % 10 == 0)
z = Math.floor(z / 10), elo--;

if (e >= digits + 2 || e < elo)
return s + m / lo + "e" + e;

if (e >= digits)
{
for (d = 1; e-- >= digits; d *= 10);
return s + m * d;
}

for (d = 1; ++e < digits; d *= 10);
return s + m / d;
}

///////////////////////////////////////////////////////////////////////////////

function SG_Calculate()
{
var f = document.SG_form;
var it, ct, ir, cr;

if (IsError(ir = ParseSG(f.ir, GetSelectValue(f.iru), 0.980, 1.144, -5, 33, "initial reading")))
return;

if (IsError(it = ParseTemp(f.it, GetSelectValue(f.itu), 32, 212, 0, 100, "temperature")))
return;

if (IsError(ct = ParseTemp(f.ct, GetSelectValue(f.ctu), 32, 212, 0, 100, "calibration temperature")))
return;

cr = ir * SG60(it) / SG60(ct);

OutputSG(f.cr, GetSelectValue(f.cru), cr);
}

///////////////////////////////////////////////////////////////////////////////

var GO_default;

function WidgetName()
{
var select = document.GO_form.widget;
return select.options[select.selectedIndex].value;
}

function GoWidget()
{
var n = WidgetName() + "0.html";
document.GO_form.widget.selectedIndex = GO_default;
location = n;
}

function PopupWidget()
{
window.open(WidgetName() + "0.html", "_blank", "scrollbars,resizable,width=450,height=350");
document.GO_form.widget.selectedIndex = GO_default;
}

///////////////////////////////////////////////////////////////////////////////

// -->
</script>

<form name="GO_form">
<p>
<table border=0 cellspacing=0 cellpadding=2 bgcolor=#ff8000 width=100%><tr><td>
<select name="widget" onChange="GoWidget()">
<option value="intro">Introduction
<option value="ac">Alcohol Content
<option value="bp">Bottle Priming
<option value="ew">Extract Weight
<option value="fc">Force Carbonation
<option value="hc" selected>Hydrometer Correction
<option value="mc">Mass Conversion
<option value="sg">Specific Gravity &amp; Plato
<option value="tc">Temperature Conversion
<option value="vc">Volume Conversion

</select>
<input type=button value="Popup" onClick="PopupWidget()">
</td></tr></table>
<font size=-1>
Enter the hydrometer reading and temperature of measurement.
Press "Calculate!" to get the calibrated reading.
</font>
</form>

<noscript>
<p><font color=#ff0000><blink>Whoops, your browser doesn't support JavaScript (or it's been disabled).</blink></font>
</noscript>

<form name="SG_form">
<p>
<table border=0><tr><td nowrap>

<table border=0 cellspacing=0 cellpadding=0>

<tr>
<td nowrap>Initial reading:&nbsp;</td>
<td><input name="ir" size=6></td>
<td>&nbsp;</td>
<td><select name="iru"><option value="sg" selected>SG<option value="p">°Plato</select></td>
</tr>

<tr>
<td nowrap>Temperature:&nbsp;</td>
<td><input name="it" size=6></td>
<td>&nbsp;</td>
<td><select name="itu"><option value="f" selected>°F<option value="c">°C</select></td>

</tr>

<tr><td>&nbsp;</td>

<tr>
<td nowrap>Calibration temperature:&nbsp;</td>
<td><input name="ct" size=6 value="68"></td>
<td>&nbsp;</td>
<td><select name="ctu"><option value="f" selected>°F<option value="c">°C</select></td>
</tr>

<tr>
<td nowrap>Corrected reading is&nbsp;</td>

<td><input name="cr" size=6></td>
<td>&nbsp;</td>
<td><select name="cru"><option value="sg" selected>SG<option value="p">°Plato</select></td>
</tr>

</table>

</td><td width=10></td><td>

<input type=button value="Calculate!" onClick="SG_Calculate()">

</td></tr></table>
</form>

<p>
 

Dippy

Moderator
Maybe.
And which are the relevant parts for what you are hoping to achieve? (Assuming its even possible as I haven't even studied it, sorry).
I just hope some kind chap has plenty of spare time.
 

Distiller

New Member
javascript with picaxe

Ok so there is the example....the actual need is quite a bit smaller but the math requirement remains....can anyone help?? Are there any professionals out there???

The limits are that the reference temperature will be fixed at 60F....one probe will be receiving temp data the other probe density. The density is calibrated at 60 F so density needs to be corrected for temperature changes above or below the calibration standard.


Brian
 

inglewoodpete

Senior Member
As a professional programmer, I'd say you're trying to implement something on the wrong processor. Yes, it could be done but it would be a substantial challenge. The PICAXE is inherently a positive integer chip and you need floating point numbers. There is a maths coprocessor chip you would need to add as well as a keypad and 2x16 LCD... but where do you stop?

Quite seriously, get yourself an old W95, W98 or XP laptop for $20 and run the java from an htm file loaded on it. An hour's work at the most.
 

MartinM57

Moderator
Are there any professionals out there???
Yes thankyou. What do you want and what is your budget :)

So what are you trying to achieve? The problem is pretty much undefined and I doubt anyone is going to bust a gut trying to decode and translate all that JS into Picaxe friendly maths.

Your original post suggests you just want to do FP maths on a Picaxe...but is this part of a control system for a real distiller (ie there are inputs and outputs that have to be interfaced with other hardware, a controlling Picaxe Basic program etc), or you just wanting to be perverse and code up a lot of maths on a Picaxe? If the latter, how do you intend getting the input values in, and the results out?

What accuracy do you really need - is all that JS just too accurate, or must it be reproduced within the Picaxe absolutely accurately? If it's too accurate, can you simplify the maths into Picaxe friendly form?
 
Last edited:
Top