-
@allObjects Holy crap thank you for that write up and explanation :-) Robin is correct, don't sell yourself short :-) Your inline char graphics is great. I'm a visual learner so your char graphics made plenty of sense.
-
require("https://raw.githubusercontent.com/espruino/EspruinoDocs/master/modules/MQTT.js")
@Gordon. Before I tested your recommendations I unplugged the ethernet cable to my raspberrypi. waited a few moments and I received MQTT disconnected... reconnecting. which stayed there for a few more moments. Then I received "Uncaught Error: This socket is closed.".
I then reconnected everything and uploaded the code with the new require. Everything connected. Removed the lan cable again..... received the MQTT disconnected message. Waite a few more moments and no Error :-)
-
I'm not infront of my computer at the moment to check the require code.
However the issue would seem to be that you were uploading your code,
running onInit() manually, and then calling save()?When I was getting the issue all I was doing was hitting the upload button then type save().
Now that I changed the Save on Send setting to "Direct to Flash (execute code at boot)" I haven't seen that Error again.
That could likely cause you other issues (like having multiple
instances of the MQTT library kicking around), so I wonder how much
it's worth bloating the MQTT lib to try and avoid that.Honestly, I wouldn't spend too much time on that. I'm the only one that seemed to run across that issue. And hooking the pico into an external supply doesn't hang while waiting for text to be dumped, so it runs as expected.
-
You might be hitting a classic Espruino USB issue here. What happens
if you power it from a USB Wall supply or Power Bank?I apologize for overlooking your first question. I used an external power source and using my original code that I posted to this thread worked as expected. To double check this again I hooked the power source back to my computers usb port and after a few msgs sent back and forth the espruino stopped responding until I connected back to the IDE so the console.log can dump to the screen.
However, even though the ping error hasn't come back, it still bugs me :-/
-
I guess the MQTT library could trap that error and then decide that
the socket had closed and tidy up.Is this something that will need to be implemented into the Espruino firmware or is this something that I would need to code into the IDE? Either way I wouldn't know where to begin to "trap the error"
-
I re-flashed the firmware onto the PICO and changed the Save on Send setting to Direct to Flash (execute code at boot). I then uploaded the code again, waited a few minutes, and I haven't received the Uncaught Error. I also commented out all of my console.log code used for debugging purposes and the PICO stopped hanging waiting to dump out the buffer.
-
Basically Espruino is using USB flow control and is trying not to lose
any text that you output with console.log - it doesn't know if the PC
isn't reading data because the IDE is busy, or because nothing is
running, so when its output buffer gets full it just waits for it to
start emptying before it continues.That makes total sense. Is it possible for the espruino to check if it is connected to a computer, if not, don't output text or just periodically clear the buffer?
Is it possible you were saving after running onInit (so it was
basically saving with an open socket connection)That sounds like what is going on. Does the current mqtt connection get terminated if the Pico looses power? Then once power is supplied again the mqtt connection should start back up as new? IF there is a fresh mqtt connection(without uploading/saving code again) I shouldn't be receiving the ping Uncaught Error as described earlier, but I still am.
-
Hardware setup: Pico, wiznet 5500io, Dual relay module
I executed save() in the IDE to save the code.
Functionality:
Pico connects to my mqtt broker and sends commands to latch/unlatch my relay.Odd behavior:
Code will execute even though there is an Error thrown; however, when I disconnect the Pico from the IDE the code doesn't execute. To debug this issue I disconnected the Pico from my computer and plugged it back in to reboot, but the code still doesn't execute.I then connected the Pico to the IDE again. Once Console.log and the Error dumps out to the screen the code executes correctly again.
Error:
Uncaught Error: This socket is closed. at line 1 col 54
this.client&&this.client.write(g(d.PINGREQ<<4)+"\x00") ^ in function
"ping" called from line 1 col 8 a.ping() ^ in function called from
systemCode:
var MQTT_HOST = "192.168.0.22"; var PATH = "/mydevice/"; var mqtt; var eth; var inProcess = false; var shortPress = 1000; // ms 1 sec var longPress = 5000; // ms 5 secs var pressPin = B3; function mqttMessage(pub) { console.log( "MQTT=> ",pub.topic,pub.message); if (pub.topic==PATH+"computer") { if (pub.message == "shutdown") { press(shortPress); } } } function mqttConnect() { console.log("mqttConnect"); mqtt = require("MQTT").connect({ host: MQTT_HOST, }); mqtt.on('connected', function() { console.log("MQTT connected"); // subscribe to wildcard for our name mqtt.subscribe(PATH+"#"); }); mqtt.on('publish', mqttMessage); mqtt.on('disconnected', function() { console.log("MQTT disconnected... reconnecting."); setTimeout(function() { mqtt.connect(); }, 1000); }); } function press(short) { // ignore press function when one is still going on if (inProcess) return; inProcess = true; //Relays act in an inverse manner //reset() will latch the relay pressPin.reset(); mqtt.publish(PATH+"shutdown/status", 1); setTimeout(function(){ //Relays act in an inverse manner //set() will unlatch the relay pressPin.set(); inProcess = false; },(short) ? shortPress : longPress); } setWatch(function(e) { digitalWrite(LED1, e.state); press(shortPress); }, BTN, { repeat: true }); function onInit() { console.log("Connecting to Ethernet"); SPI2.setup({ mosi:B15, miso:B14, sck:B13 }); eth = require("WIZnet").connect(SPI2, B10); isConnected = eth.setIP(); if (isConnected == true) { mqttConnect(); } }
-
I'm assuming I connected the two breadboard wires to my computer's 'soft' power switch.
I removed the cases shutdown button wires from my motherboard header and replaced them with my circuits gnd lead and the lead coming from the relay.
The circuit is powered from one of my usb ports located on the front 0f my computer case.
-
My project consists of an Espruino Pico, Wiznet5500io and a 2 Relay Module. I am using node-red and mqtt on my raspberry pi 3 to communicate with the Pico. I am using these parts to turn on and shutdown my computer. I mainly use my computer as a media server which is located downstairs in my office. My TV is located upstairs. I normally shut my computer off when it's not in use so I can save on my electric bill. Instead of walking downstairs to turn on/off my computer I figured I can comfortably do that from my cell phone via from my couch :-)
The pico controls the relay. The relay is connected to my motherboard shutdown header. The relay is triggered for a second to short the header to gnd when it receives the mqtt msg of "shutdown" or if the button on top of the pico is pressed. Triggering the relay will turn my computer on or shutdown my computer if its all ready on.
With the help of @alldata I was able to use his suggestions to get a working prototype :-)
Any critiques/suggests are welcomed.
I eventually want to create a pcb, but first I need to figure out fritzing.
Guides that I followed:
Todo:
- Create a cleaner fritzing sketch
- Add some gauges in node-red to receive feedback
Create a PCB
var turnedOFF = 1; var isConnected = false; var MQTT_HOST = "192.168.0.22"; var PATH = "/mydevice/"; var mqtt; var eth; function mqttMessage(pub) { console.log("pub: " + pub.message); console.log( "MQTT=> ",pub.topic,pub.message); if (pub.topic==PATH+"computer") { //var v = pub.message!=0; //console.log(v); if (pub.message == "shutdown") { trigger(); mqtt.publish(PATH+"onoff/status", 1); } if (pub.message == "0") { mqtt.publish(PATH+"onoff/status", 0); } //digitalWrite(B3, v); } } function mqttConnect() { console.log("mqttConnect"); mqtt = require("MQTT").connect({ host: MQTT_HOST, }); mqtt.on('connected', function() { console.log("MQTT connected"); // subscribe to wildcard for our name mqtt.subscribe(PATH+"#"); }); mqtt.on('publish', mqttMessage); mqtt.on('disconnected', function() { console.log("MQTT disconnected... reconnecting."); setTimeout(function() { mqtt.connect(); }, 1000); }); } /*setInterval(function() { if (!mqtt) return; mqtt.publish( PATH+"cputemp", E.getTemperature()); }, 2*60*1000);*/ function trigger() { turnedOFF = 1; digitalPulse(B3,0,1000); digitalWrite(LED1, 0); console.log("digitalWrite"); } setWatch(function(e) { digitalWrite(LED1, e.state); trigger(); }, BTN, { repeat: true }); function onInit() { console.log("Connecting to Ethernet"); SPI2.setup({ mosi:B15, miso:B14, sck:B13 }); eth = require("WIZnet").connect(SPI2, B10); //console.log("Connect?: " + isConnected); isConnected = eth.setIP(); //console.log("Connect?: " + isConnected); if (isConnected == true) { mqttConnect(); } } /*setWatch(function() { if (!mqtt) return; mqtt.publish( PATH+"buttonpress", 1); }, BTN, {edge:"rising",repeat:true,debounce:50});*/
- Create a cleaner fritzing sketch
-
@Gordon I think I meant to say setIP instead of getIP in my original post. I would like to execute mqttConnect(); after espruino successfully connects to the network via a callback. Implementing a callback on both setIP and getIP would be great. Thank you for submitting an issue.
-
I figured this out. setIP() returns true when it successfully finishes.
Updated onInit code:
function onInit() { console.log("Connecting to Ethernet"); SPI2.setup({ mosi:B15, miso:B14, sck:B13 }); eth = require("WIZnet").connect(SPI2, B10); console.log("Connect?: " + isConnected); isConnected = eth.setIP(); console.log("Connect?: " + isConnected); if (isConnected == true) { mqttConnect(); } //eth.getIP(); eth.getIP(function(f,ip) { console.log("IP: ",ip); mqttConnect(); }); }
-
I've been attempting to connect to mqtt using the WIZ550io instead of wifi without success. My goal is to use a pico + WIZ550io + mqtt to trigger relays. I doubled checked if my pico has an IP address by typing eth.getIP() into the IDE console and I get the following result:
={ "ip": "192.168.0.21", "subnet": "255.255.255.0", "gateway": "192.168.0.1", "dns": "************", "mac": "00:08:dc:1e:b9:73" }
I'm following this guide: http://www.espruino.com/Home+Automation
I think my issue is with in my onInit function. I'm trying to call mqttConnect(); on a successful
eth.getIP
, but I don't think
mqttConnect()
is getting called:
eth.getIP(function(f,ip) { console.log("IP: ",ip); mqttConnect(); });
code:
var turnedOFF = 1; var MQTT_HOST = "192.168.0.22"; var PATH = "/mydevice/"; var mqtt; var eth; function mqttMessage(pub) { console.log( "MQTT=> ",pub.topic,pub.message); if (pub.topic==PATH+"onoff") { var v = pub.message!=0; digitalWrite(B3, !v); mqtt.publish(PATH+"1/status", v?1:0); } } function mqttConnect() { console.log("mqttConnect"); mqtt = require("MQTT").connect({ host: MQTT_HOST, }); mqtt.on('connected', function() { console.log("MQTT connected"); // subscribe to wildcard for our name mqtt.subscribe(PATH+"#"); }); mqtt.on('publish', mqttMessage); mqtt.on('disconnected', function() { console.log("MQTT disconnected... reconnecting."); setTimeout(function() { mqtt.connect(); }, 1000); }); } setInterval(function() { if (!mqtt) return; mqtt.publish( PATH+"cputemp", E.getTemperature()); }, 2*60*1000); function trigger() { turnedOFF = 1; digitalPulse(B3,0,1000); digitalWrite(LED1, 0); console.log("digitalWrite"); } setWatch(function(e) { digitalWrite(LED1, e.state); trigger(); }, BTN, { repeat: true }); function onInit() { console.log("Connecting to Ethernet"); SPI2.setup({ mosi:B15, miso:B14, sck:B13 }); eth = require("WIZnet").connect(SPI2, B10); eth.setIP(); //eth.getIP(); eth.getIP(function(f,ip) { console.log("IP: ",ip); mqttConnect(); }); }
-
@allObjects greetings, I sent you a pm..
-
@allObjects howdy. It has been awhile since I updated my status on this project/your code. Turns out, the PH sensor that I am using from atlas-scientific is a bit older and buggy which in turn doesn't give me proper readings so I resorted to checking my water ph using the old fashioned method i.e. using the General Hydroponics Test Kit solution. I guess doing things the "old fashioned" way gets the job done :-)
Now, I'm looking for another project for the espruino.
-
-
-
-
@allobjects I haven't forgotten the help you have given me so far. My day time job is consuming most of my time ATM - it's that time for the holiday season :-/ I'm hoping in the next few days I will give your example code a try on the Espruino. I will for sure respond back.
-
@allobjects again thank you. Most of what you wrote went WAY over my head; however, It didn't go to waste. You have given me valuable information that I can google to learn more.
-
@allObjects I read through your posts(a few times). I'm definitely needing to split my code up more. In case you are interested... I posted links to the sensors. I would of liked to upload the datasheets, but every time I tried to upload a file I keep getting: "Internal Server Error".
Temp Sensor
http://www.atlas-scientific.com/_files/_datasheets/_circuit/EZO_RTD_Datasheet.pdfPH Sensor
http://www.atlas-scientific.com/_files/_datasheets/_circuit/pH_EZO_datasheet.pdfEC Sensor
http://www.atlas-scientific.com/_files/_datasheets/_circuit/EC_EZO_Datasheet.pdf? -
@allObjects thanks again for your write up. I especially like the explanation you gave about CRC. Your explanations gave me some insights about what I can and should do differently.
-
For what it's worth here is my code that I hacked together before you responded a second time to my my original post. Its rather messy and I could probably do this a different way especially change the nested setTimeouts. The reason why I used setTimouts is to wait before I gather the other sensor data. On average, it takes 300ms to process a "read command" then I can issue a a "readFrom". On some occasions, depending on the sensor, it can take 1300ms to process a "read command" before I can issue an I2C "readFrom". The nested timeouts allows me to:
First, send a read command to the temp sensor then take the temp
value and update the ph and ec temperature compensation json data.
Also, save the temp value to a json object.Second, send a temp compensation update command to both the ph and
ec sensor. It takes 300ms for each of the ph and ec sensors to process
that command.Third, send a ph read command and wait 300ms to execute an i2c
readFrom the ph sensor to gather the data. Also, save the ph value
to a json object.Fourth, send an ec read command and wait 1300ms to execute an i2c
readFrom the ec sensor to gather the data. Also, save the ec value
to a json object.After all that I send the JSON object via serial to another device.
Another reason for my nested timeouts was, well atleast I thought, If I send a read command to both the ph and ec sensors at the the same time(after their temp compensations was updated), thought the i2c would crash or timeout...
I'll have to read through your post and attempt to implement the information into my code.
I2C1.setup({scl:B8, sda:B9}); Serial2.setup(9600/*baud*/); var resTempVal = 0; var phVal = ""; var ecVal = ""; var ready = true; var alwaysTempCompensate = false; var sensorReadings = { restempvalue : 0, phvalue : 0, ecvalue : 0 }; //console.log(sensorReadings.phvalue); function Sensor(id, type, address, buffer) { this.sensorName = id; this.sensorType = type; this.sensorAddress = address; this.sensorResultBuff = buffer; //this.sensorReading = ""; this.sensorRequireTempComp = false; this.sensorResTempValue = 0; this.resTempCal = { "clear" : { "cmd" : "Cal,Clear", "wait" : 300 }, "one" : { "cmd" : "Cal,n", "wait" : 1300 }, "query" : { "cmd" : "Cal,?", "wait" : 300 } }; this.phCal = { "clear" : { "cmd" : "Cal,Clear", "wait" : 300 }, "mid" : { "cmd" : "Cal,mid,7.00", "wait" : 1300 }, "low" : { "cmd" : "Cal,low,4.00", "wait" : 1300 }, "high" : { "cmd" : "Cal,high,10.00", "wait" : 1300 }, "query" : { "cmd" : "Cal,?", "wait" : 300 } }; this.ecCal = { "clear" : { "cmd" : "Cal,Clear", "wait" : 300 }, "dry" : { "cmd" : "Cal,dry", "wait" : 2000 }, "one" : { "cmd" : "Cal,one,n", "wait" : 1300 }, "low" : { "cmd" : "Cal,low,n", "wait" : 1300 }, "high" : { "cmd" : "Cal,high,n", "wait" : 1300 }, "query" : { "cmd" : "Cal,?", "wait" : 300 } }; this.cmdTable = { "Calibrate" : { //List of Calibration commands and timeout value. }, "Information" : { //Device Information }, "LED" : { //Enable / Disable or Query the LEDs "L0" : { "cmd" : "L,0", "wait" : 300 }, "L1" : { "cmd" : "L,1", "wait" : 300 }, "L?" : { "cmd" : "L,?", "wait" : 300 } }, "Reading" : { //Takes a single reading "R" : { "cmd" : "r", "wait" : 1000 } //Takes a single temperature compensated reading }, "Serial" : { //Switch back to UART mode }, "Sleep" : { //Enter low power sleep mode }, "Status" : { //Retrieve status information }, "Temperature" : { //Set or Query the temperature compensation "T" : { "cmd" : "T,19.5", "wait" : 300 }, //Where the temperature is any value; floating point, or int, in ASCII form "T?" : { "cmd" : "T,?", "wait" : 300 } //Query the set temerature }, "Factory" : { //Factory reset }, }; if (type == "temp") { this.cmdTable.Calibrate = this.resTempCal; var celsiusVal = 0; } if (type == "ph") { this.cmdTable.Calibrate = this.phCal; this.sensorRequireTempComp = true; } if (type == "ec") { this.cmdTable.Calibrate = this.ecCal; this.sensorRequireTempComp = true; } } Sensor.prototype.updateTempCompJSON = function (temp) { //console.log("Temp Comp: " + temp); this.cmdTable.Temperature.T.cmd = "T," + temp; }; Sensor.prototype.updateTempComp = function () { var a = this.sensorAddress; var cmd = this.cmdTable.Temperature.T.cmd; I2C1.writeTo(a, cmd); }; Sensor.prototype.takeReading = function(callback) { var a = this.sensorAddress; var c = this.cmdTable.Reading.R.cmd; var w = this.cmdTable.Reading.R.wait; var b = this.sensorResultBuff; var d = ""; var sensorStatus = ""; var sensorValue = ""; var captureSensorData = false; I2C1.writeTo(a, c); setTimeout(function () { d = I2C1.readFrom(a, b); if (d.length > 0) { var dContent = d[0]; switch (dContent) { case 1: sensorStatus = 1; captureSensorData = true; break; case 255: sensorStatus = 255; break; case 254: sensorStatus = 254; break; case 2: sensorStatus = 2; break; } if (captureSensorData === true) { for (i = 1; i < d.length; i++) { sensorValue += String.fromCharCode(d[i]); } } } captureSensorData = false; callback(sensorValue); }, w); }; var restemp = new Sensor("RES TEMP", "temp", 77, 9); var ph = new Sensor("PH", "ph", 78, 9); var ec = new Sensor("EC", "ec", 99, 14); function getAllSensorData() { setTimeout(function () { restemp.takeReading(function(val) { var f = parseFloat(val).toFixed(1); var celsiusVal = (5/9) * (f-32); //console.log(celsiusVal); sensorReadings.restempvalue = f; setTimeout(function () { ph.updateTempCompJSON(celsiusVal.toFixed(1)); ph.updateTempComp(); }, 1000); setTimeout(function () { ec.updateTempCompJSON(celsiusVal.toFixed(1)); ec.updateTempComp(); }, 2000); console.log("RES TEMP READING: " + sensorReadings.restempvalue); }); }, 100); setTimeout(function () { ph.takeReading(function(val) { var f = parseFloat(val).toFixed(1); sensorReadings.phvalue = f; console.log("PH READING: " + sensorReadings.phvalue); }); }, 4000); setTimeout(function () { ec.takeReading(function(val) { var f = val; sensorReadings.ecvalue = f; console.log("EC READING: " + sensorReadings.ecvalue); }); }, 5300); } setInterval(function () { //console.log("Taking Reading: "); getAllSensorData(); }, 10000);
@Gordon I noticed after about 3 MQTT messages are received by the Espruino I get:
It's nothing major, everything seems to run.
Thank you for everything that you have been doing for Espruino community :-)