CH_PD shouldn't matter - just tie it to 3V and leave it like that.
Reset can be left floating for the moment, or tie it to 3V.
Yes, red led on and two flashes on the blue led means the module is working.
Power it up and listen on the Tx pin. It will output some data and a signon message. In general terms, any pin with Tx on it is an output.
The signon message will be either 115200 or 9600 baud - it depends on the module. If the baud rate is incorrect, it will output random characters, but at least you will get characters and that is useful information.
My first experiments did not use an arduino or a propeller.
I started very simple - a USB to serial cable, and a D9 female plug with pins 2 and 3 soldered together.
I then used a free terminal program on a PC and checked that a character typed on the keyboard would echo on the screen. That tested my USB serial cable was working.
I then built a RS232 to 3V TTL converter using a max3232 chip. I then connected the TTL side of the max3232 Tx to Rx and checked that characters typed on the terminal program would echo on the screen. This tested the max3232 was working correctly.
I then connected just the Tx pin of the ESP module to the Rx pin on the max3232 and checked I could get the signon message.
I then connected the Rx pin on the ESP module to the max3232 and tried typing something in the terminal program - the simplest command is AT and then return. The terminal program allows the baud rate to be changed so it didn't matter which baud rate it started up at.
Then I spent a lot of time manually typing in commands.
Then I wrote a vb.net program to automate the startup routine so I could test each instruction more quickly.
Another way to do this if you have an arduino board is to use the arduino as a repeater. There is an example in softwareserial and it is just two lines of code - scan a port for a byte, if byte received send it on.
I haven't tried Spin yet but I imagine I'll start with a serial object and again, just scan for bytes and send them on to the Propeller Tool terminal program.
If you are having trouble, maybe a photo of your setup?
I changed the baudrate from 115200 to 9600 and now the code from user "ProcessingData" is working.
I get a response from the module
So this means I jumped to the level of what is the right order to send commands.
As I'm using the propeller-chips USB-connection as debug-channel anyway
What's the best way to code something like this:
using Propeller-Serial-terminal (PST) to type in ESP8266-commands in PST
propeller-chip receives these commands and does forward the commands to the ESP8266
ESP8266 responds then the code forwards the response to PST.
So I want to do it all on a propeller without any ard....
I think in the propeller terminal (F12) type the text to send in the one line box at the top of the screen, then hit enter?
Try AT and then enter.
What I am not sure about is the enter bit. The enter you type might just send AT. Or you can write a line of code to send AT<CR>
The startup sequence is
AT+CWMODE=3
AT+CWJAP="routername","routerpassword"
AT+CIFSR ' should return the IP address the router has assigned it
AT+CIPMUX=1
but from then on it gets a bit more complex to get a website - you need to build a string to send, and work out the length, then tell the module how long the string is you are about to send it, then send exactly that number of bytes. So from that point on, probably better to write it in code rather than manually typing commands.
thank you very much for your answer.
Yes this is a good way to test something new. Basic principle use components that are proven to work reliably to examine where the bug is.
Anyway I did test it in a different way:
I managed to get user "ProcessingData" 's code to work and tinkered around with it.
I was able to connect to an accesspoint and to query the IP-Adress.
What I do not understand is why the module sometimes needs some seconds to respond
especially the answer for query IP-Adress with "AT+CIFSR" if the "AT+CIFSR"-command comes too quick the ESP8266 will respond "busy p...."
Does anybody know what the rules are behind the responding behaviour of the ESP8266?
My presumptions are
the ESP8266 answers first with an echo of the command sended to it
in some cases it responds additionally with an "OK"
in other cases it responds with "busy p..."
So what I'm looking for is how to establish some kind of handshaking
- send a command
- wait for acknowledge
if the ESP8266 should send an answer
- wait for answer
the ESP8266 sends back messages.
Is there any kind of a constant "End-of-message-character or a character-sequence indicating end-of-message?
Can I indicate End-of-Message just by "5 seconds no new characters" ??
Does anybody know a website with informations about this?
Without informations about this it's almost reverse-engineering
This description shows Type of command (query or execute
exact command-string
Response of the ESP8266 to the command
description of the Function of the ESP8266 AT-command and an example how to use the command
at the end of the menu (on the right side) there is a link to AT-command-sequences how to do
single connection (ESP8266 as TCP client)
transparent transmission
multiple connection (ESP8266 as TCP server)
UDP transmission
If somebody wants to save time for newbees collecting information each and single again and again
post some small democode how to communicate with the ESP8266-module
Now that I found it I'm very glad to drive up the learning-curve
As I make progress I will post it here in this thread...
best regards
Stefan
still wondering why it needed me to post these links .... ts ts ts
Is there any kind of a constant "End-of-message-character or a character-sequence indicating end-of-message?
No, there isn't. I've been working three solid days on this. Every command has its own ways of responding and they are not documented.
Can I indicate End-of-Message just by "5 seconds no new characters" ??
That is a good place to start - use a 5 second loop and echo all the characters back to some sort of display so you can get a feel for how it works. But then it takes 30 seconds to get onto a website, and it is possible to do this faster.
About half the commands respond with OK if something worked, so it is useful to have a routine that looks for this string, and times out either when OK arrives or if it takes more than 5 seconds. So in many cases that is a response in 100ms or less.
But then there are the other commands that fail with strange text, "busy p..." is one of them, and there is "link is not" and when a link is disconnected, you get "Unlink" rather than OK. They don't seem to be all listed on that github site.
I've written a new routine to catch most of these and which times out quicker. It starts by waiting for any character. If nothing after 5 seconds, it times out. If there is a character, gobble up all characters until there are none left. This assumes that at 9600 baud, the esp8266 is sending characters faster than 9600, so when they stop coming, that is the end of the data.
Also I don't think it matters so much if the response is OK. Requesting a website takes five or six steps, and any one can fail, and if each fails then it can either go back to the start, or fall through to the next command which will definitely fail. So if looking up a website is seen as a package of code, it either works or it doesn't.
I've simplified it so that a Led is on if google is live. That makes debugging much easier.
One big problem is that the IP address is not fixed and I haven't got to the stage of reflashing the module so it can fix an IP address. No problem if running as a client, but for a server, if the router reboots, clients might not be able to reconnect.
Instead of a server, I'm looking at uploading data to somewhere like xively. I'm getting close to getting that working, hopefully will do it today.
As for running a client as a simple browser, well, this is going to be a job for the Propeller, because the standard arduino code only has small serial port buffers which overrun and miss some of the data. No problem with the propeller, just grab a serial object with a large buffer from the Obex.
So this might be a project where the propeller could really shine. Calling all Propellerheads!
This is the latest arduino code. Unfortunately I've hit a brick wall at the moment.
This code does work - it will check for a connection to google (ie acting as a client, or a simple browser) and it then changes mode and runs as a server, and you can connect to it by typing the IP address into any browser.
I hope I have put in enough comments!
Lots of dead ends along the way. I did once or twice get it talking to xively and doing file transfers but it was intermittent, and I think I can trace that to using a lot of strings which gobbles the 2k ram in the arduino very quickly and then the heap and the stack start overwriting each other. So I put in code to print out text using data from flash rather than ram. But it still needs a decent amount of ram space as you build a web page by joining lots of strings, then finally you have to work out the total length, and then insert that between the header and the data. So for that you need strings. I got sidetracked in C with trying to put constant strings into flash instead of ram, and there is a way to do this with PROGMEM but it won't copy strings properly, so I tried doing it one byte at a time but I'm not sure how to get the length of the string in PROGMEM, and even if you do, you have to write a separate decode routine for every static string. It becomes a dogs breakfast to code.
The good thing about the arduino is a lot of code has been written so it is possible to get things working. But the 2k ram limitation is a real problem, especially as it is hard to know what the heap and stack really are up to.
So ... time to port all this over to Spin with a decent amount of memory!
/*
ESP8266 module - run from arduino 3V3 supply but needs a 4700uF capacitor on the 3V line
CH_PD pulled high
newer ESP8266 modules boot at 9600 but can be reprogrammed back to 115200
reset pin to arduino pin 12 so can do hardware resets
echo data to arduino terminal
The ESP8266 is 3V and arduino is 5V, the ESP8266 chip can handle ? up to 6V on the pins
in theory, need a 5V to 3V level converter
in practice, a 10k and 20k resistor divider didn't work, and connecting the 5V directly did work.
Testing the current through a 100R resistor, getting only microamps, so conclusion is that it is ok to directly connect to arduino.
The circuit:
* RX is digital pin 10 (connect to TX of other device)
* TX is digital pin 11 (connect to RX of other device)
*/
#include <SoftwareSerial.h>
//#include <avr/pgmspace.h> // saves ram, can store strings in flash as the little UNO only has 2k of ram and every quote uses this
#define SSID "Oslo_Cabin" // insert your SSID
#define PASS "" // insert your password (blank if no password)
#define destHost "www.google.com"
#define destPage "/"
#define destPort "80"
#define RxPin 10
#define TxPin 11
#define espRstPin 12
#define diagLedPin 13
#define serverLoopDelay 30 // server stays alive for this number of seconds, if a connection, then listens, if no connection then try google
PROGMEM prog_uchar signMessage[] = {"Hello World"};
// xively values
#define APIKEY "shsCNFtxuGELLZx8ehqglXAgDo9lkyBam5Zj22p3g3urH2FM" // replace your pachube api key here
#define FEEDID "970253233" // replace your feed ID
#define USERAGENT "Arduino1" // user agent is the project name
SoftwareSerial espSerial(RxPin, TxPin); // RX, TX
char outBuff[256]; // store in one place rather than building strings and then copying them around in memory (or could use pointers)
int outBuffLen = 0; // can't use 0 as an end of string marker as might need to send out this as a valid binary character
String commandString = ""; // use .reserve on strings to save fixed memory. Use F when printing strings to store that string in flash
void setup()
{
// Open serial communications and wait for port to open:
Serial.begin(115200); // for debugging
while (!Serial) {
; // wait for serial port to connect.
}
commandString.reserve(40); // use one general command string, avoids strange bugs with fragmented memory building tiny strings
Serial.println(F("Starting Arduino"));
espSerial.begin(9600);
pinMode(diagLedPin, OUTPUT); // diagnostic led
pinMode(espRstPin, OUTPUT); // ESP8266 reset pin
digitalWrite(diagLedPin,LOW); //led off
printFreeRam();
//testStringMemory();
rebootTestInternet();
}
void loop()
{
serverLoop(serverLoopDelay); // if getting connections keep the server going, if no connections for n seconds, check google is still live
quickTestInternet(); // is google still contactable?
//sendXively("sensor1",47);
//delay(10000);
//quickTestInternet();
//delay(4000);
}
void testStringMemory()
{
//int k=0;
//char c;
//c = pgm_read_byte_near(signMessage + k);
//Serial.println(c);
//strcpy_P(outBuff, (char*)pgm_read_word(&(signMessage))); // Necessary casts and dereferencing, just copy. - crashed the program
}
boolean rebootTestInternet()
{
boolean reply = false;
resetESP8266(); // gets out of any hangs, eg if two browsers try to read at the same time
flashLed();
commandAT();
commandCWMODE();
flashLed();
connectWiFi();
displayIPaddress(); // useful for debugging and working out what address this has been assigned, could skip this
flashLed();
commandCIPMUX();
flashLed();
reply = commandGOOGLE();
return reply;
}
void quickTestInternet() // for second and subsequent tests, no need to disconnect the router etc
{
boolean googleAlive = false;
// Serial.println("Test internet alive");
flashLed();
googleAlive = commandGOOGLE();
if (googleAlive == false) { // failed to reconnect so do a complete reboot and keep trying till reconnects
do
{
googleAlive = rebootTestInternet();
} while (googleAlive == false); // keep repeating if can't reconnect
}
}
void resetESP8266()
{
int i;
Serial.println(F("Hardware reset ESP8266"));
digitalWrite(12,LOW);
delay(200);
digitalWrite(12,HIGH);
for(i=0;i<1000;i++) // echo the startup message
{
if (espSerial.available())
Serial.write(espSerial.read());
delay(1);
}
}
void commandAT()
{
espSerial.println(F("AT"));
if(delayOK())
Serial.println(F("AT OK"));
}
void commandCWMODE()
{
espSerial.println(F("AT+CWMODE=3"));
delay(200); // replies with "no change" not OK so need custom code here
if(espSerial.find("no change")) {
Serial.println(F("CWMODE OK"));
}else{
Serial.println(F("Error CWMODE")); // the very first time the module runs this, will return an error, but remembers this forever in eeprom
}
}
//void requestIPaddress() // this is a new function ?Dec 2014 and might not be available on some modules. Can set the IP address
//{
// espSerial.println("AT+CIPSTA=\"192.168.1.70\"");
// waitReply(); // see all the text that comes back
//}
boolean delayOK() // times out after 8 seconds or if no OK. Sometimes takes 4 to 5 serial.find loops ie 4-5 seconds to respond
{
int i = 0;
boolean abort = false;
serialFlush(); // remove any leftover things
do
{
if(espSerial.find("OK")) {
abort = true; // will abort the loop
}
i+=1;
}
while ((abort == false) && (i<8));
}
void serialFlush(){
while(Serial.available() > 0) {
char t = Serial.read();
}
}
boolean connectWiFi()
{
commandString ="AT+CWJAP=\""; // global big string variable
commandString += SSID;
commandString += "\",\"";
commandString += PASS;
commandString += "\"";
Serial.println(commandString);
espSerial.println(commandString);
if(delayOK()){
Serial.println(F("OK, Connected to WiFi"));
return true;
}else{
Serial.println(F("Cannot connect to the WiFi"));
return false;
}
}
void displayIPaddress() // a useful way to check actually connected
{
espSerial.println(F("AT+CIFSR"));
waitReply();
}
void waitReply() // wait for a character then prints out, the esp8266 is faster than arduino so once all the bytes have stopped that is it
{
int counter = 0;
do {
counter +=1;
delay(1);
} while ((counter<3000) && (!espSerial.available())); // wait until one character comes in or times out
while (espSerial.available()) {
Serial.write(espSerial.read()); // print out the text, might be just a reply, or even an entire web page
}
}
void commandCIPMUX()
{
espSerial.println(F("AT+CIPMUX=1"));
if(delayOK())
Serial.println(F("CIPMUX OK"));
}
boolean commandGOOGLE() // connect to google to test internet connectivity
{
boolean reply = false;
int count = 0;
Serial.println(F("Test google home page"));
commandString = "AT+CIPSTART=0,\"TCP\",\"";
commandString += destHost;
commandString += "\",80";
espSerial.println(commandString);
Serial.println(commandString);
if(delayOK())
Serial.println(F("CIPSTART OK"));
espSerial.find("Linked");
outBuffClear(); // clear the output buffer prior to adding new data to send
outBuffAppend("GET ");
outBuffAppend(destPage);
outBuffAppend(" HTTP/1.1\r\nHost: ");
outBuffAppend(destHost);
outBuffAppend(":");
outBuffAppend(destPort);
outBuffAppend("\r\n\r\n");
commandSendBuff("0"); // send this data
//waitReply(); // display what comes back - this does seem to overrun the buffer, not sure why as works at 9600 into vb.net
// or light a led if got a correct website
while ((reply == false) && (count <4))
{
if(espSerial.find("Found"))
{
digitalWrite(diagLedPin,HIGH); // led on, found a website
Serial.println(F("Reply from GOOGLE"));
reply = true;
}
count +=1;
}
delay(1000);
espSerial.flush();
commandCIPCLOSEzero();
return reply; // true or false
}
void commandCIPCLOSEzero() // close port zero
{
espSerial.println(F("AT+CIPCLOSE=0")); // close the connection from this end
Serial.println(F("Close connection"));
waitReply();
}
void commandSendBuff(String ch_id) // sends outbuff array
{
int i;
commandString = "AT+CIPSEND=";
commandString += ch_id;
commandString += ",";
commandString += String(outBuffLen);
espSerial.println(commandString);
Serial.println(commandString); // for debugging
espSerial.find(">"); // wait for the command prompt to come back
for (i=0;i<outBuffLen;i++) {
espSerial.write(outBuff[i]); // output a byte
//Serial.write(outBuff[i]); // debugging, might slow things down?
}
}
void flashLed()
{
digitalWrite(diagLedPin,HIGH);
delay(50);
digitalWrite(diagLedPin,LOW);
}
void serverLoop(int timeout) // if getting regular connections then no need to check google
{
boolean hits = false;
do
{
hits = runServer(timeout); // if get a hit then keep looping as no need to check google all the time
} while (hits == true);
}
boolean runServer(int timeout) // http://mcuoneclipse.com/2014/11/30/tutorial-web-server-with-the-esp8266-wifi-module/
// timeout is in seconds
{
int channelNumber;
int counter = 0;
boolean connection = false;
commandAT(); // see if module is awake, sometimes it is busy from a previous command
Serial.println(F("Starting server"));
delay(1000);
espSerial.println(F("AT+CIPSERVER=1,80")); // set up a server, 1 means open connection (0 is close), 80 is the port
waitReply(); // can't look for OK, as sometimes replies as no change, and sometimes as busy
Serial.println(F("Connect now from a browser"));
//need this next line to time out after a while so can recheck if still on the internet
while ((espSerial.find("+IPD,") == false) && (counter < timeout)) // this is the login routine, and the next character will be the port number
{
counter +=1; // one second
Serial.print(timeout - counter); // countdown timer
}
if (counter < timeout) { // must have got a connection, so process it, otherwise fall through and close off
Serial.print(F("\n\rGot a connection on channel "));
channelNumber = espSerial.read() - 48; // 48 is ascii 0
Serial.println(channelNumber);
waitReply();
Serial.println(F("\n\rServing home page now"));
serveHomePage(channelNumber); // or can just send some text, if replying to another node, or even just send "Hello"
delay(2000); //delay
waitReply();
Serial.println(F("\n\rClose connection"));
espSerial.println(F("AT+CIPCLOSE=0")); // must close connection before browser will display anything - returns Unlink so can't look for ok
delay(100);
waitReply();
//espSerial.println("AT+CIPSERVER=0"); // turn off server mode - need to wait a bit after cipclose, otherwise returns busy, please wait
//delay(100); // not sure if cipserver=0 is needed, will need to do more testing, does this disable google next cylcle, or just bad luck with my link?
Serial.println(F("Finished closing"));
connection = true;
}else{
Serial.println(F("\r\nNo connections received"));
espSerial.println(F("AT+CIPSERVER=0")); // close down the server as nothing happened
waitReply();
}
return connection;
}
void serveHomePage(int ch_id) { // http://christinefarion.com/2014/12/esp8266-serial-wifi-module/
{
String header = "";
String content = "";
header = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n";
// header += "Connection: close\r\n"; // or close with cipclose from this end
content="";
// output the value of each analog input pin
for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
int sensorReading = analogRead(analogChannel);
content += "analog input ";
content += analogChannel;
content += " is ";
content += sensorReading;
content += "<br />\n";
}
header += "Content-Length:";
header += (int)(content.length());
header += "\r\n\r\n";
// print to debug, then to wifi
Serial.print("AT+CIPSEND=");
Serial.print(ch_id);
Serial.print(",");
Serial.println(header.length()+content.length());
Serial.print(header);
Serial.print(content);
espSerial.print("AT+CIPSEND=");
espSerial.print(ch_id);
espSerial.print(",");
espSerial.println(header.length()+content.length());
espSerial.print(header);
espSerial.print(content);
}
}
//char server[] = "api.xively.com"; // name address for xively API
/*
// this method makes a HTTP connection to the server:
void sendXively(String sensorName, int data)
{
String xivelyData;
Serial.println("Please wait");
delay(4000);
Serial.println("Connecting to xively");
String cmd = "AT+CIPSTART=0,\"TCP\",\"";
cmd += "api.xively.com";
cmd += "\",80";
espSerial.println(cmd);
waitReply();
delay(3000);
waitReply();
//Serial.println(cmd);
//if(delayOK()) {
// Serial.println("CIPSTART OK");
//}else{
// Serial.println("CIPSTART fail");
//}
xivelyData = sensorName;
xivelyData += ",";
xivelyData += String(data);
// build the put string - can't send as one long string so send in pieces
// or maybe put in an array first
commandSend("PUT /v2/feeds/");
commandSend(FEEDID);
commandSend(".csv HTTP/1.1\r\nHost: api.xively.com\r\nX-ApiKey: ");
commandSend(APIKEY);
commandSend("\r\nUser-Agent: ");
commandSend(USERAGENT);
commandSend("\r\nContent-Length: ");
commandSend(String(xivelyData.length())); // length of the data string
commandSend("\r\nContent-Type: text/csv\r\nConnection: close\r\n\r\n");
commandSend(xivelyData); // the actual data to send
commandSend("\r\n\r\n"); // ? 1 or 2 crlfs
//delay(5000);
waitReply();
delay(4000);
waitReply();
commandCIPCLOSEzero();
waitReply();
}
*/
void outBuffClear()
{
outBuffLen = 0; // resent the counter. Can't reset the array to zero as zero is a valid binary number
}
void outBuffAppend(String s)
{
int i;
int st;
int fin;
int ln;
char c;
st = outBuffLen; // start at the beginning
ln = s.length();
fin = outBuffLen + ln;
if (ln == 0) {
Serial.println(F("Error - zero string length - buffer not being filled"));
}
if (fin < 256) { // add string if there is space
for(i=0;i<ln;i++) {
c = s.charAt(i); // get the character, make sure it is a character
outBuff[st] = c; // store it in the array
st += 1; // increment the st value
}
outBuffLen += ln;
}else{
Serial.println(F("Buffer overrun"));
}
}
void outBuffInsert(String s) // inserts data at the beginning, shuffles existing data up. Safer than using strings as the buffer is predefined
{
}
void outBuffPrint() // for debugging, print out all the values in hex
{
int i;
char c;
for(i=0;i<outBuffLen;i++) {
c=outBuff[i];
Serial.print(c);
printHex(outBuff[i]);
}
}
void printHex(char x) {
if (x < 16) {Serial.print(F("0"));}
Serial.print(x, HEX);
Serial.print(" ");
}
void printFreeRam()
{
Serial.print(F("Free ram = "));
Serial.println(freeRam());
}
int freeRam () {
extern int __heap_start, *__brkval;
int v;
return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}
If I understand right there is a SDK for the ESP8266
has anybody seen somebody working on a more reliable and easier to use firmware and well documented firmware?
Somehow this remembers me of the legendary C64. Somehow the C64 was so bad that there was much space for improvements
(Datasette-speedup, Ultraload, other programming-languages than Comodore basic etc)
I took a quick look at the start guide AT-Commands.
The AT-Commands have the same letters. Does this mean the WEE-Module has the same firmware as the other module?
If the wee has the same (in my opinion a bit crappy) firmware the wee has no advantage over the other module.
Less than 5$ per module is pretty cheap.
But if this means the firmware has no consistent concept on how to respond on messages with a uniform "End-Of-Message"-sequence
I will go back to modules in the 20-80$-range
In the long run this kind of beeing cheap is expensive.
I took a look at the cc3000 Breakout-board
seems aatractive
Then I came acros the the "Electric Imp" ... does anybody have experience with it.
Would the Electric Imp be a choice if I want to send/receive some smaller amount of data via WiFi?
I could be wrong but as far as I know it requires your IoT thing to communicate with servers in the "cloud" that are an Electric Imp service (or whatever the company is called). That is to say a centralized, system, not "cloud" at all.
I've designed a new propeller board - see attached. Has a socket for the wifi module. Over at Seeed PCB they always have a great price for 10x10cm boards, so I've just managed to fit it on that size board. All the extras I find useful - SD card, VGA, TV, keyboard, analog inputs, some level translation to 5V, and the wifi module.
from a quick reading the description how to flash the firmware sounds a bit complicated.
Maybe it just sounds to me complicated because I'm not familiar with SDKs toolchains and python.
Is anybode more into it and can estimate the effort or could do a quick test of flashing it.
Me myself I have fear to do something wrong that the flashing fails and then the module would be useless
Hi Stefan, No I haven't tried reflashing the module either. Looks a bit complicated.
Where are you stuck? I know all the commands are a bit different but there are not very many. The core of the routine to talk to Google is just five commands - reset, CWMODE, connect wife (ssid, password), CIPMUX, then send text. The send text is split into two parts - the command with how many bytes you want to send, and then send that number of bytes.
boolean rebootTestInternet()
{
resetESP8266(); // gets out of any hangs
commandCWMODE();
connectWiFi();
commandCIPMUX();
reply = commandGOOGLE();
}
in my earlier life I was working as a software developer for machine-controls. Somehow "embedded". The machines were not controlled by small mcus but with industrial PCs.
Anyway I had to make the software as foolproof as possible. Thinking about ANY possible crazy configuration or crazy situation you could the machine set into.
(In a car assembly-shop maintenance-workers know very little about every machine. Enough to be willing to try things but not enough to try senseful things)
So I'm used to make things foolproof. I'm not really stucked but responding messages like "busy...." makes me suspicious what will happen if....
@Dr_Acula
you posted some pseudo-code
resetESP8266(); // gets out of any hangs
commandCWMODE();
connectWiFi();
commandCIPMUX();
reply = commandGOOGLE();
would you share the real code behind it?
resetESP8266 "gets out of any hangs"
sounds promising
from my experience to get the ESP8266 out of EVERY hang
I estimated I have to insert a power-switch for rebooting the ESP8266 controlled by the propeller-chip
and if this would be really nescessary to get the ESP8266 out of EVERY hang that would be far away from what I would call a reliable working device.
@stefan, full code in post #69 above. Sorry, my C is not the best. This has been working for about a week now. Ran out of memory to do xively though.
pjv said.. Now that sounds like a challenging project. I don't know anyone who would even consider reflashing his wife !
@pjv, yea, you got me *grin*.
A man received the following text from his neighbour:
I am so sorry Bob. I've been riddled with guilt and I have to confess. I have been tapping your wife, day and night when you're not around.
In fact, more than you. I'm not getting any at home, but that's no excuse. I can no longer live with the guilt and I hope you will accept my sincerest apology with my promise that it won't happen again.
The man, anguished and betrayed, went into his bedroom, grabbed his gun, and without a word, shot his wife and killed her.
Received my two ESP8266-05's (approx. 15mm x 15mm) today. Only five connections - rst, 0v, rx, tx, 3v3 and ufl aerial connector.
I had soldered on pin header and breadboarded a basic serial connection via a Prop Plug. FATAL. I wasn't receiving any start up messages and shortly after the smell of something rather hot.
So are they 5V tolerant or not?
The ESP was showing on my tablets wireless sniffer so I quickly programmed a quick start with the spin code from an earlier post, cobbled it all together and still nothing. Looks like I may have fried the rx/tx op/IP of the ESP.
I'll plug the other ESP into the Quickstart tomorrow and see how I go.
UPDATE: It's alive!
These ESP8266 are hardy modules. Clearly they are tolerant of a little 5V action on the rx pin but also ... when reconnecting it to the Quickstart I stupidly swapped the +3v3 and 0v to the ESP.
I only noticed this when the smell of hotness became apparent and I saw the blue led on the QS was not on. Quickly unplugging the USB cable revealed a very hot regulator on the QS.
Fearing the worst I corrected my wiring and carefully plugged in the second ESP, uploaded some new spin to the QS and nothing.
Hmmm>
A quick check of the spin program and a quick edit and "whoila" a response from the ESP.
Feeling lucky I plugged in the first ESP and "hot dang" it responded.
today I did some research on alternative firmwares for the ESP8266.
So I came across the ESP8266 NodeMCU firmware.
This website gives a quickstart introduction to how to flash a ESP8266-module with the NodeMCU firmware http://benlo.com/esp8266/esp8266QuickStart.html
Looks promising to me. Gonna try this out.
What I find most annoying about the standardfirmware is the lack of a uniform "end-of-message" bytesequence.
I also read some posts about a bug making the firmware hang in a "busy..." mode which can only be recovered by a hard-reset power-off-on.
(Hm this remembers me of a somehow famous OS making the user do a similar thing for a lot of reasons.... ;-)
Does anybody here in the forum know how "Lua" works?
Is Lua able to receive single commands and sending answers in an interactive way?
This would make things easier
I've never used Lua (until 5 minutes ago). If you type lua at a prompt, it does go into an interactive mode and you can type valid lua and it will be evaluated. A difference between lua and python (for example) is that python sees everything as an expression with a value and prints that value as part of the interactive loop. Lua, on the other hand sees everything entered as a statement. you need to prefix what you type with an '=' for it to be valid and print.
For example, in python:
Python 2.7.3 (default, Mar 18 2014, 05:13:23)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 5 + 3
8
>>>
This probably makes more sense once you understand lua but it's as much as I learned in 5 minutes of Google and play. (oh, and lua appears to be installed as a standard package on Raspbian)
Thanks for finding/sharing NodeMCU! It will have to be added to my list of things to play with.
accidentally I have DS1820-sensors laying around ;-) and tested it. The original lua-script uses 18B20 (12bit resolution)
I modified the script to use the DS1820 (9bit resolution) and wow! cool! - it works!!
Now that's pretty slick!!
So IoT becomes really easy and cheap.
A german internet-shop for electronics sells a battery powered electronic radiator thermostatic valve for just 10€ (=$10)
I have two of them. They are working good for 4 weeks now.
So I'm thinking about using the mechanical part of them and as new electronic an ESP8266 with 5-8 GPIO-Pins, a small H-bridge for driving the motor
and a DS18B20 sending data to a WiFi-connected server (Spinneret Webserver ;;-)) which holds all temperature-over-time-profiles for each valve
controling all valves by receiving the temperature-values and opening/closing the valves by sending commands to them.
Ah, that looks very interesting Stefan. You could do a lot with a few pins, and if you need more pins, could get another ESP module as they are so cheap.
I need to test out the ESP module and the propeller. The Arduino ran out of space for strings and it got very frustrating when the string space started overwriting the heap/stack space and giving strange errors. For talking to Xively and real IoT projects I think it will need a few kilobytes of string space as you need to build a string and then insert the length of the string in the middle of that string. The propeller has plenty of space for this.
Lua looks interesting - I need to read more about that.
I have also run into a small problem with the reliability of routers. My home setup has a main modem then a number of repeaters and then repeaters for those repeaters and each router needs resetting every week or so, and when you have 4 or 5 of them, the whole network fails almost every day. I think it might be a temperature problem - many routers are not rated over 40C and in Australia, that can mean routers will fail for 3-4 months of the year. A shed can easily get to 55C. I'm using a combination of timer switches and extractor fans in sheds and router boxes with their cases removed and little heatsinks glued to the hot chips and extra fans blowing on those heatsinks. Finally... I have something vaguely reliable.
No-one told me the IoT was going to be this hard!! Or maybe the IoT is being developed in a colder climate?
Wow, where did you find that technique?
You have opened up a whole new vista of Java Script programming:
function ǝʞɐɯ () {
var ʇɐɥʇ;
this.ǝsuǝs = function () {
ʇɐɥʇ = {};
}
}
var ǝʞɐɯ = new ǝʞɐɯ();
ǝʞɐɯ.ǝsuǝs();
</div>Wow, where did you find that technique?<br />
<div class="bbcode_container">
<div class="bbcode_description">Code:</div>
<pre class="bbcode_code"style="height:132px;">function ǝʞɐɯ () {
var ʇɐɥʇ;
this.ǝsuǝs = function () {
ʇɐɥʇ = {};
}
}
var ǝʞɐɯ = new ǝʞɐɯ();
ǝʞɐɯ.ǝsuǝs();</pre>
</div>
does this mean that the upper numbers of unicode are defined as letters upside down?
EDIT; oh no it even shows up in my quotation. OK gonna attach a picture of it
It's all the magic of unicode. That upside down text is all just valid unicode characters. Same like α,β,γ,δ,...
all that ʞ stuff is just how you get unicode into a text using good old ASCII printable characters
It just happens that JavaScript allows a ot of those unicode characters to be used as symbol names.
Comments
Reset can be left floating for the moment, or tie it to 3V.
Yes, red led on and two flashes on the blue led means the module is working.
Power it up and listen on the Tx pin. It will output some data and a signon message. In general terms, any pin with Tx on it is an output.
The signon message will be either 115200 or 9600 baud - it depends on the module. If the baud rate is incorrect, it will output random characters, but at least you will get characters and that is useful information.
My first experiments did not use an arduino or a propeller.
I started very simple - a USB to serial cable, and a D9 female plug with pins 2 and 3 soldered together.
I then used a free terminal program on a PC and checked that a character typed on the keyboard would echo on the screen. That tested my USB serial cable was working.
I then built a RS232 to 3V TTL converter using a max3232 chip. I then connected the TTL side of the max3232 Tx to Rx and checked that characters typed on the terminal program would echo on the screen. This tested the max3232 was working correctly.
I then connected just the Tx pin of the ESP module to the Rx pin on the max3232 and checked I could get the signon message.
I then connected the Rx pin on the ESP module to the max3232 and tried typing something in the terminal program - the simplest command is AT and then return. The terminal program allows the baud rate to be changed so it didn't matter which baud rate it started up at.
Then I spent a lot of time manually typing in commands.
Then I wrote a vb.net program to automate the startup routine so I could test each instruction more quickly.
Another way to do this if you have an arduino board is to use the arduino as a repeater. There is an example in softwareserial and it is just two lines of code - scan a port for a byte, if byte received send it on.
I haven't tried Spin yet but I imagine I'll start with a serial object and again, just scan for bytes and send them on to the Propeller Tool terminal program.
If you are having trouble, maybe a photo of your setup?
I changed the baudrate from 115200 to 9600 and now the code from user "ProcessingData" is working.
I get a response from the module
So this means I jumped to the level of what is the right order to send commands.
As I'm using the propeller-chips USB-connection as debug-channel anyway
What's the best way to code something like this:
using Propeller-Serial-terminal (PST) to type in ESP8266-commands in PST
propeller-chip receives these commands and does forward the commands to the ESP8266
ESP8266 responds then the code forwards the response to PST.
So I want to do it all on a propeller without any ard....
best regards
Stefan
Try AT and then enter.
What I am not sure about is the enter bit. The enter you type might just send AT. Or you can write a line of code to send AT<CR>
The startup sequence is
AT+CWMODE=3
AT+CWJAP="routername","routerpassword"
AT+CIFSR ' should return the IP address the router has assigned it
AT+CIPMUX=1
but from then on it gets a bit more complex to get a website - you need to build a string to send, and work out the length, then tell the module how long the string is you are about to send it, then send exactly that number of bytes. So from that point on, probably better to write it in code rather than manually typing commands.
thank you very much for your answer.
Yes this is a good way to test something new. Basic principle use components that are proven to work reliably to examine where the bug is.
Anyway I did test it in a different way:
I managed to get user "ProcessingData" 's code to work and tinkered around with it.
I was able to connect to an accesspoint and to query the IP-Adress.
What I do not understand is why the module sometimes needs some seconds to respond
especially the answer for query IP-Adress with "AT+CIFSR" if the "AT+CIFSR"-command comes too quick the ESP8266 will respond "busy p...."
Does anybody know what the rules are behind the responding behaviour of the ESP8266?
My presumptions are
the ESP8266 answers first with an echo of the command sended to it
in some cases it responds additionally with an "OK"
in other cases it responds with "busy p..."
So what I'm looking for is how to establish some kind of handshaking
- send a command
- wait for acknowledge
if the ESP8266 should send an answer
- wait for answer
the ESP8266 sends back messages.
Is there any kind of a constant "End-of-message-character or a character-sequence indicating end-of-message?
Can I indicate End-of-Message just by "5 seconds no new characters" ??
Does anybody know a website with informations about this?
Without informations about this it's almost reverse-engineering
best regards
Stefan
hm - I'm asking myself "what's so hard about posting where the most relevant information can be found"?
my personal answer posting some links is not hard at all. It is easy.
So why did nobody else do it before? - don't know.
maybe everyone was so eager to test it that they didn't take time for it.
Anyway. One part of the most relevant information is the documentation of the AT-Commandset
can be found here https://github.com/espressif/esp8266_at/wiki/AT_Description
This description shows Type of command (query or execute
exact command-string
Response of the ESP8266 to the command
description of the Function of the ESP8266 AT-command and an example how to use the command
at the end of the menu (on the right side) there is a link to AT-command-sequences how to do
single connection (ESP8266 as TCP client)
transparent transmission
multiple connection (ESP8266 as TCP server)
UDP transmission
https://github.com/espressif/esp8266_at/wiki/at_example_0020000903
If somebody wants to save time for newbees collecting information each and single again and again
post some small democode how to communicate with the ESP8266-module
Now that I found it I'm very glad to drive up the learning-curve
As I make progress I will post it here in this thread...
best regards
Stefan
still wondering why it needed me to post these links .... ts ts ts
Is there any kind of a constant "End-of-message-character or a character-sequence indicating end-of-message?
No, there isn't. I've been working three solid days on this. Every command has its own ways of responding and they are not documented.
Can I indicate End-of-Message just by "5 seconds no new characters" ??
That is a good place to start - use a 5 second loop and echo all the characters back to some sort of display so you can get a feel for how it works. But then it takes 30 seconds to get onto a website, and it is possible to do this faster.
About half the commands respond with OK if something worked, so it is useful to have a routine that looks for this string, and times out either when OK arrives or if it takes more than 5 seconds. So in many cases that is a response in 100ms or less.
But then there are the other commands that fail with strange text, "busy p..." is one of them, and there is "link is not" and when a link is disconnected, you get "Unlink" rather than OK. They don't seem to be all listed on that github site.
I've written a new routine to catch most of these and which times out quicker. It starts by waiting for any character. If nothing after 5 seconds, it times out. If there is a character, gobble up all characters until there are none left. This assumes that at 9600 baud, the esp8266 is sending characters faster than 9600, so when they stop coming, that is the end of the data.
Also I don't think it matters so much if the response is OK. Requesting a website takes five or six steps, and any one can fail, and if each fails then it can either go back to the start, or fall through to the next command which will definitely fail. So if looking up a website is seen as a package of code, it either works or it doesn't.
I've simplified it so that a Led is on if google is live. That makes debugging much easier.
One big problem is that the IP address is not fixed and I haven't got to the stage of reflashing the module so it can fix an IP address. No problem if running as a client, but for a server, if the router reboots, clients might not be able to reconnect.
Instead of a server, I'm looking at uploading data to somewhere like xively. I'm getting close to getting that working, hopefully will do it today.
As for running a client as a simple browser, well, this is going to be a job for the Propeller, because the standard arduino code only has small serial port buffers which overrun and miss some of the data. No problem with the propeller, just grab a serial object with a large buffer from the Obex.
So this might be a project where the propeller could really shine. Calling all Propellerheads!
http://www.esp8266.com/
but see you have been there already
so just for others ...
This code does work - it will check for a connection to google (ie acting as a client, or a simple browser) and it then changes mode and runs as a server, and you can connect to it by typing the IP address into any browser.
I hope I have put in enough comments!
Lots of dead ends along the way. I did once or twice get it talking to xively and doing file transfers but it was intermittent, and I think I can trace that to using a lot of strings which gobbles the 2k ram in the arduino very quickly and then the heap and the stack start overwriting each other. So I put in code to print out text using data from flash rather than ram. But it still needs a decent amount of ram space as you build a web page by joining lots of strings, then finally you have to work out the total length, and then insert that between the header and the data. So for that you need strings. I got sidetracked in C with trying to put constant strings into flash instead of ram, and there is a way to do this with PROGMEM but it won't copy strings properly, so I tried doing it one byte at a time but I'm not sure how to get the length of the string in PROGMEM, and even if you do, you have to write a separate decode routine for every static string. It becomes a dogs breakfast to code.
The good thing about the arduino is a lot of code has been written so it is possible to get things working. But the 2k ram limitation is a real problem, especially as it is hard to know what the heap and stack really are up to.
So ... time to port all this over to Spin with a decent amount of memory!
has anybody seen somebody working on a more reliable and easier to use firmware and well documented firmware?
Somehow this remembers me of the legendary C64. Somehow the C64 was so bad that there was much space for improvements
(Datasette-speedup, Ultraload, other programming-languages than Comodore basic etc)
best regards
Stefan
http://imall.iteadstudio.com/wireless/gsm-gprs-and-wifi/im141118001.html
P.S I'm still working on full featured driver for the CC3000 (day job takes to much out of my time)
I took a quick look at the start guide AT-Commands.
The AT-Commands have the same letters. Does this mean the WEE-Module has the same firmware as the other module?
If the wee has the same (in my opinion a bit crappy) firmware the wee has no advantage over the other module.
Less than 5$ per module is pretty cheap.
But if this means the firmware has no consistent concept on how to respond on messages with a uniform "End-Of-Message"-sequence
I will go back to modules in the 20-80$-range
In the long run this kind of beeing cheap is expensive.
I took a look at the cc3000 Breakout-board
seems aatractive
Then I came acros the the "Electric Imp" ... does anybody have experience with it.
Would the Electric Imp be a choice if I want to send/receive some smaller amount of data via WiFi?
best regards
Stefan
I could be wrong but as far as I know it requires your IoT thing to communicate with servers in the "cloud" that are an Electric Imp service (or whatever the company is called). That is to say a centralized, system, not "cloud" at all.
Is that good or bad? Depends what you want to do.
today I found an alternative firmware it's called ESP8266 xPL V1.2
https://github.com/peteben/xPL-ESP8266/wiki/Getting-started
from a quick reading the description how to flash the firmware sounds a bit complicated.
Maybe it just sounds to me complicated because I'm not familiar with SDKs toolchains and python.
Is anybode more into it and can estimate the effort or could do a quick test of flashing it.
Me myself I have fear to do something wrong that the flashing fails and then the module would be useless
best regards
Stefan
Where are you stuck? I know all the commands are a bit different but there are not very many. The core of the routine to talk to Google is just five commands - reset, CWMODE, connect wife (ssid, password), CIPMUX, then send text. The send text is split into two parts - the command with how many bytes you want to send, and then send that number of bytes.
boolean rebootTestInternet()
{
resetESP8266(); // gets out of any hangs
commandCWMODE();
connectWiFi();
commandCIPMUX();
reply = commandGOOGLE();
}
Now that sounds like a challenging project. I don't know anyone who would even consider reflashing his wife !
Heck, I don't even know my wife's SSID !
Cheers,
Peter (pjv)
Anyway I had to make the software as foolproof as possible. Thinking about ANY possible crazy configuration or crazy situation you could the machine set into.
(In a car assembly-shop maintenance-workers know very little about every machine. Enough to be willing to try things but not enough to try senseful things)
So I'm used to make things foolproof. I'm not really stucked but responding messages like "busy...." makes me suspicious what will happen if....
@Dr_Acula
you posted some pseudo-code
would you share the real code behind it?
resetESP8266 "gets out of any hangs"
sounds promising
from my experience to get the ESP8266 out of EVERY hang
I estimated I have to insert a power-switch for rebooting the ESP8266 controlled by the propeller-chip
and if this would be really nescessary to get the ESP8266 out of EVERY hang that would be far away from what I would call a reliable working device.
best regards
Stefan
pjv said.. Now that sounds like a challenging project. I don't know anyone who would even consider reflashing his wife !
@pjv, yea, you got me *grin*.
A man received the following text from his neighbour:
I am so sorry Bob. I've been riddled with guilt and I have to confess. I have been tapping your wife, day and night when you're not around.
In fact, more than you. I'm not getting any at home, but that's no excuse. I can no longer live with the guilt and I hope you will accept my sincerest apology with my promise that it won't happen again.
The man, anguished and betrayed, went into his bedroom, grabbed his gun, and without a word, shot his wife and killed her.
A few moments later, a second text came in:
Damn autocorrect. I meant "wifi", not "wife".
I had soldered on pin header and breadboarded a basic serial connection via a Prop Plug. FATAL. I wasn't receiving any start up messages and shortly after the smell of something rather hot.
So are they 5V tolerant or not?
The ESP was showing on my tablets wireless sniffer so I quickly programmed a quick start with the spin code from an earlier post, cobbled it all together and still nothing. Looks like I may have fried the rx/tx op/IP of the ESP.
I'll plug the other ESP into the Quickstart tomorrow and see how I go.
UPDATE: It's alive!
These ESP8266 are hardy modules. Clearly they are tolerant of a little 5V action on the rx pin but also ... when reconnecting it to the Quickstart I stupidly swapped the +3v3 and 0v to the ESP.
I only noticed this when the smell of hotness became apparent and I saw the blue led on the QS was not on. Quickly unplugging the USB cable revealed a very hot regulator on the QS.
Fearing the worst I corrected my wiring and carefully plugged in the second ESP, uploaded some new spin to the QS and nothing.
Hmmm>
A quick check of the spin program and a quick edit and "whoila" a response from the ESP.
Feeling lucky I plugged in the first ESP and "hot dang" it responded.
Now to get on with my DMX-Wifi (Art-Net) project.
today I did some research on alternative firmwares for the ESP8266.
So I came across the ESP8266 NodeMCU firmware.
This website gives a quickstart introduction to how to flash a ESP8266-module with the NodeMCU firmware
http://benlo.com/esp8266/esp8266QuickStart.html
Looks promising to me. Gonna try this out.
What I find most annoying about the standardfirmware is the lack of a uniform "end-of-message" bytesequence.
I also read some posts about a bug making the firmware hang in a "busy..." mode which can only be recovered by a hard-reset power-off-on.
(Hm this remembers me of a somehow famous OS making the user do a similar thing for a lot of reasons.... ;-)
Does anybody here in the forum know how "Lua" works?
Is Lua able to receive single commands and sending answers in an interactive way?
This would make things easier
best regards
Stefan
For example, in python:
in lua:
This probably makes more sense once you understand lua but it's as much as I learned in 5 minutes of Google and play. (oh, and lua appears to be installed as a standard package on Raspbian)
Thanks for finding/sharing NodeMCU! It will have to be added to my list of things to play with.
As the ESP8266 is a SoC (System on Chip) for small tasks there is no propeller-chip needed.
I found a project on instructables
it uses the above mentioned nodeMCU-firmware with a lua script that: ....
tata! reads the temperature of a DS18B20 onewire temperaturesensor and sends the data to thingspeak.com.
just by connecting the DS1820 to the ESP8266 directly.
http://www.instructables.com/id/Low-cost-WIFI-temperature-data-logger-based-on-ESP/?lang=de&ALLSTEPS
accidentally I have DS1820-sensors laying around ;-) and tested it. The original lua-script uses 18B20 (12bit resolution)
I modified the script to use the DS1820 (9bit resolution) and wow! cool! - it works!!
Now that's pretty slick!!
So IoT becomes really easy and cheap.
A german internet-shop for electronics sells a battery powered electronic radiator thermostatic valve for just 10€ (=$10)
http://www.pollin.de/shop/dt/NTgzNjMxOTk-/Haustechnik/Heizung_Sanitaer/Heizkoerper_Thermostatkopf_eQ_3_Model_N.html
I have two of them. They are working good for 4 weeks now.
So I'm thinking about using the mechanical part of them and as new electronic an ESP8266 with 5-8 GPIO-Pins, a small H-bridge for driving the motor
and a DS18B20 sending data to a WiFi-connected server (Spinneret Webserver ;;-)) which holds all temperature-over-time-profiles for each valve
controling all valves by receiving the temperature-values and opening/closing the valves by sending commands to them.
So something like the openTRV http://www.earth.org.uk/open-source-programmable-thermostatic-radiator-valve.html
becomes much more compact
best regards
Stefan
I need to test out the ESP module and the propeller. The Arduino ran out of space for strings and it got very frustrating when the string space started overwriting the heap/stack space and giving strange errors. For talking to Xively and real IoT projects I think it will need a few kilobytes of string space as you need to build a string and then insert the length of the string in the middle of that string. The propeller has plenty of space for this.
Lua looks interesting - I need to read more about that.
I have also run into a small problem with the reliability of routers. My home setup has a main modem then a number of repeaters and then repeaters for those repeaters and each router needs resetting every week or so, and when you have 4 or 5 of them, the whole network fails almost every day. I think it might be a temperature problem - many routers are not rated over 40C and in Australia, that can mean routers will fail for 3-4 months of the year. A shed can easily get to 55C. I'm using a combination of timer switches and extractor fans in sheds and router boxes with their cases removed and little heatsinks glued to the hot chips and extra fans blowing on those heatsinks. Finally... I have something vaguely reliable.
No-one told me the IoT was going to be this hard!! Or maybe the IoT is being developed in a colder climate?
Not a heat issue, placement issue!
you know that you have to place them upside down on your half of the world?
Just asking.
Mike
¡ǝsuǝs sǝʞɐɯ ʇɐɥʇ 'ɥ∀
You have opened up a whole new vista of Java Script programming: Thanks!
I don't know anything about javascript and html.
I took a look into the firefox sourcecode window
and found this
does this mean that the upper numbers of unicode are defined as letters upside down?
EDIT; oh no it even shows up in my quotation. OK gonna attach a picture of it
best regards
Stefan
¡ǝɯ oʇ ʞo ʎlʇɔǝɟɹǝd sʞool ʇxǝʇ uʍop ǝpᴉsdn s,ɹǝʇɐǝɥ
all that ʞ stuff is just how you get unicode into a text using good old ASCII printable characters
It just happens that JavaScript allows a ot of those unicode characters to be used as symbol names.
For other tricks with unicode and JavaScript see here:http://forums.parallax.com/showthread.php/159724-JavaScript
Dr_A, Great, finally a programming language for Australians. I hope Tachyon can do this:)