-
Looking forward to this. I used to have plans to digitise SCX cars in some way but I always talked myself out of it saying that I might as well just do it as a computer game rather than interacting with the real world.
You could do awesome things like simulating engine wear which causes the cars to drive slower, track the cars as they move around the track and do lap counting this way. If you're putting the Pixl on board the car then you could display what place in the race the cars are on the roof.
-
-
Still looking for some more optimisations here as I'm running out of memory.
@Gordon the docs for https://www.espruino.com/Reference#t_heatshrink say it doesn't support streaming, but I know that the C implementation does. Is this something you could look at changing?
-
I went with https://www.npmjs.com/package/heatshrink-ts just had to configure it with the
WINDOW_BITS, LOOKAHEAD_BITS, INPUT_BUFFER_LENGTH
parameters that you found for me.
-
-
@Gordon its just using heatshrink. More savings to be made if we sent just the changes as well but we'd need two packet types then, one for the initial "full" send, and then another for just updates.
@urish I will work on a pull request, the code is very bad at the moment. I need to send 1 frame of all 0x00 bytes before the real frames, then 1 frame of 0xFF bytes so that we can identify the "real" frames and make sure they are in order (sometimes they out OOO even though BLE should order them). I'm sure there are many improvements to be made.
-
-
@opichals If you are running your code snippet on your local machine, then where are you running the code that does the calls to other Graphics functions like drawString, etc?
-
Might be a little tricky to explain, but sometimes on the Pixl screen I get messages that appear like this:
Bluetooth
< Bluetoothor similar (I could add a photo if this is not clear).
I'm guessing these are coming from the Espruino OS. Just wondering if I could turn these off in any way?
I tried Terminal.setConsole(false) but this obviously causes issues trying to connect with the IDE.
Any thoughts?
-
@Gordon thanks for the info.
With that typescript example, the decoder requires two parameters that I don't know the values of which I'm hoping you can tell me!
WINDOW_BITS and LOOKAHEAD_BITS. I'm guessing these are the configuration properties from https://github.com/atomicobject/heatshrink/#configuration so hopefully you have set this somewhere in the Espruino source that I can't find and you can tell me what they are :D
-
Hi @Gordon,
Just wondering if you can provide any more details on https://www.espruino.com/Reference#t_heatshrink ?
Is the output encoded in any way? Is https://github.com/polygonplanet/lzbase62 likely to be able to decode Heatshrink compressed data? Or do you know of any other JS implementation of Heatshrink that will let me decompress?
Edit: Looks like we had exactly the same thoughts for what I'm trying to achieve: http://forum.espruino.com/comments/14468542/ still interested if you've had any further ideas on how I could decompress in JS-land.
-
@opichals could you give me a full usage example?
Not sure if I'm just being stupid but is your module supposed to get flashed to the Pixl? If so then how does it create a websocket server? I'm just getting ">Uncaught InternalError: Not connected to the internet" as an error.
-
-
So I know that the IDE will convert and display data/img style images, but is there any way we can mirror the display in a slightly more real-time fashion?
I'm guessing there might not be enough bandwidth over the BLE connection... maybe an Espruino emulator?
Edit: http://forum.espruino.com/conversations/326858/ is basically what I was after
-
Ah, perfect. I just need to read your docs better. I was stuck on http://www.espruino.com/Reference#Graphics looking through all the functions and didn't see the link to http://www.espruino.com/Graphics which would have lead me to http://www.espruino.com/BMPLoader
-
Hi Gordon,
Is there an inverse equivalent of https://www.espruino.com/Reference#l_Graphics_asURL ? I.e if I've got a base64 encoded image, can I convert it to something I can pass to Graphics to display on the screen?
-
-
-
Ahh, so I have to throw away the 'ATE0' response because echo is not off at the time of issuing the command to turn echo off.
at.cmd('', 10000, function cb(data) { if (data && data!="ready") return cb; at.cmd('ATE0\r\n', 10000, function cb(data) { if (data=="ATE0") return cb; console.log(data); // ask for version at.cmd('AT+GMR\r\n', 10000, function(data) { console.log(data); }); }); }); // power up
] "\nAi-Thinker Technology Co.,Ltd.\r\n\r\nready\r\n" <--- "\nAi-Thinker Technology Co.,Ltd.\r\n\r\nready\r\n"
["ATE0\r\n"
] "ATE0\r\r\n\r\nOK\r\n" <--- "ATE0\r\r\n\r\nOK\r\n"
OK
["AT+GMR\r\n"
] "AT version:0.40.0." <--- "AT version:0.40.0."
] "AT version:0.40.0.0(Aug 8 2015 14:45:58)\r\nSDK " <--- "0(Aug 8 2015 14:45:58)\r\nSDK "
AT version:0.40.0.0(Aug 8 2015 14:45:58)
] "SDK version:1.3.0\r\nAi-Thinker Technology Co.,Ltd.\r\nBuild:1.3.0.2 Sep" <--- "version:1.3.0\r\nAi-Thinker Technology Co.,Ltd.\r\nBuild:1.3.0.2 Sep"
] "Build:1.3.0.2 Sep 11 2015 11:48:04\r\nOK\r\n" <--- " 11 2015 11:48:04\r\nOK\r\n" -
Something odd is definitely happening.
at.cmd('', 10000, function cb(data) { if (data && data!="ready") return cb; at.cmd('ATE0\r\n', 10000, function (data) { console.log(data); // ask for version at.cmd('AT+GMR\r\n', 10000, function(data) { console.log(data); }); }); }); // power up
] "\nAi-Thinker Technology Co.,Ltd.\r\n\r\nready\r\n" <--- "\nAi-Thinker Technology Co.,Ltd.\r\n\r\nready\r\n"
["ATE0\r\n"
] "ATE0\r\r\n\r\nOK\r\n" <--- "ATE0\r\r\n\r\nOK\r\n"
ATE0
["AT+GMR\r\n"
OK
] "AT version:0.40.0.0(Aug 8 2015 14:45:58)\r\nSDK version:1.3.0\r\nAi-Thinker Technology Co.,L" <--- "AT version:0.40.0.0(Aug 8 2015 14:45:58)\r\nSDK version:1.3.0\r\nAi-Thinker Technology Co.,L"
] "Ai-Thinker Technology Co.,Ltd.\r\nBuild:1.3.0.2 Sep 11 2015 11:48:04\r\nOK\r\n" <--- "td.\r\nBuild:1.3.0.2 Sep 11 2015 11:48:04\r\nOK\r\n"Logging
data
always seems to be "behind" by one response. -
Hmm, no wait, same thing on the old firmware:
["AT+GMR\r\n"
] "AT+GMR\r\r\nAT versio" <--- "AT+GMR\r\r\nAT versio"
AT+GMR
] "AT version:0.40.0.0(Aug 8 2015 14:45:58)\r\nSDK version:1.3.0\r\nAi-Thinker Technology C" <--- "n:0.40.0.0(Aug 8 2015 14:45:58)\r\nSDK version:1.3.0\r\nAi-Thinker Technology C"
] "Ai-Thinker Technology Co.,Ltd.\r\nBuild:1.3.0.2 Sep 11 2015 11:48:04\r\nOK\r\n" <--- "o.,Ltd.\r\nBuild:1.3.0.2 Sep 11 2015 11:48:04\r\nOK\r\n" -
I never got those instructions to work when I originally tried so this was with a method I knew worked already :)
It looks like either the AT or the Espruino_WiFi module don't like the newer firmware which is a problem for me :(
Here's what happens when I run your code sample with
at.debug();
["AT+GMR\r\n"
] "AT+GMR\r\r\nAT version" <--- "AT+GMR\r\r\nAT version"
AT+GMR
] "AT version:1.3.0.0(Jul 14 2016 18:54:01)\r\nSDK version:2.0.0(656edbf)\r\ncompile time:Ju" <--- ":1.3.0.0(Jul 14 2016 18:54:01)\r\nSDK version:2.0.0(656edbf)\r\ncompile time:Ju"
] "compile time:Jul 19 2016 18:43:55\r\nOK\r\n" <--- "l 19 2016 18:43:55\r\nOK\r\n"So it just prints 'AT+GMR' as the
console.log
, it seems like something returns too early. I'm guessing its because of the\r\r\n
separator? Not sure why its double\r
. -
Here is a set of instructions for anyone who wishes to flash the ESP8266 on their Espruino WiFi to a newer firmware.
Undertake at your own risk, this involves some fiddly soldering, weird commands, strange cables, and other dark magic. Here be dragons.
First, solder two cables to the ESP8266 chip underneath your Espruino WiFi. See the attached image.
Next, take your 3v3 FTDI cable and connect the ESP8266 TX to FTDI RXD, and ESP8266 RX to FTDI TXD. Then connect GND on FTDI to the Espruino WiFi GND (-) pin.
Download the ESP8266 NONOS SDK V2.0.0 20160810 firmware from https://espressif.com/en/support/download/sdks-demos. I know the V2.1.0 firmware is released, but it does not support the version of ESP8266 that you have.
Unzip the firmware to your local machine. The files you want are inside
ESP8266_NONOS_SDK/bin
.Install esptool.py version 1.3 to your machine, this is dependant on your OS, so its up to you to get this done.
Once installed, you need to edit the python file with your text editor. Find it, and then look for the following lines:
ESP_RAM_BLOCK
ESP_FLASH_BLOCK
Make sure they look like this:
ESP_RAM_BLOCK = 0x80 ESP_FLASH_BLOCK = 0x80
If you can't find these blocks, you probably don't have version 1.3, go back and try again.
Open a new terminal window and navigate to the directory with the new firmware. Remember to be in the directory
ESP8266_NONOS_SDK/bin
so you can seeesp_init_data_default.bin
,blank.bin
, and a directory calledat
. Ignoreat_sdio
directory.Plug in your FTDI cable to your computer and work out what device it is. For me on OS X it was:
/dev/cu.usbserial-FT97O28F
but this is very likely to be different for you.Next, connect your Espruino WiFi USB, then open your Espruino IDE. On the left side, paste and run:
digitalWrite(A14,0); // power off digitalWrite(A13,0); // boot mode digitalWrite(A14,1); // power on digitalRead(A2); digitalRead(A3);
Now for the magic command:
esptool.py -p /dev/cu.usbserial-FT97O28F -b 115200 write_flash 0x00000 at/noboot/eagle.flash.bin 0x10000 at/noboot/eagle.irom0text.bin 0x7c000 esp_init_data_default.bin 0x78000 blank.bin 0x7a000 blank.bin 0x7e000 blank.bin
replace
/dev/cu.usbserial-FT97O28F
with the relevant FTDI device path for you, but everything else should stay the same.The output should look like this:
esptool.py v1.3 Connecting..... Auto-detected Flash size: 32m Running Cesanta flasher stub... 0 Flash params set to 0x0040 Wrote 45056 bytes at 0x0 in 3.9 seconds (91.6 kbit/s)... Wrote 372736 bytes at 0x10000 in 32.3 seconds (92.2 kbit/s)... Wrote 4096 bytes at 0x7c000 in 0.4 seconds (85.5 kbit/s)... Wrote 4096 bytes at 0x78000 in 0.4 seconds (85.4 kbit/s)... Wrote 4096 bytes at 0x7a000 in 0.4 seconds (85.4 kbit/s)... Wrote 4096 bytes at 0x7e000 in 0.4 seconds (85.4 kbit/s)... Leaving...
Unplug your FTDI cable, restart your Espruino WiFi.
Currently I'm not sure how to verify it is working in an easy way (you can connect directly to the ESP8266 using FTDI and issue
AT+GMR
). This code on Espruino should work, but I just see 'ready' as the output. Maybe @Gordon could shed some light.E.on('init', function() { setTimeout(function() { digitalWrite(A14, 0); Serial2.setup(115200, { rx: A3, tx : A2, cts: A15 }); const at = require('AT').connect(Serial2); at.cmd('AT+RST\r\n', 10000, function(data) { at.cmd('AT+GMR\r\n', 10000, function(data) { console.log(data); }); }); digitalWrite(A13, 1); digitalWrite(A14, 1); }, 1000); });
It would be great if someone else could test these steps, especially @Gordon, and it would be really-really great if the next version of Espruino WiFi has ESP8266 pins broken out somewhere :D
-
So after a bit of fiddling, I've come up with the following that seems to work. I'm sure this has been done before and in a better and more reliable way, but this is what I have.
PC Sound Generator:
AudioContext = window.AudioContext || window.webkitAudioContext; audioContext = new AudioContext(); gainNode = audioContext.createGain(); gainNode.gain.value = 1; var buffer = audioContext.createBuffer(1, 44100, 44100); var b = buffer.getChannelData(0); function fillAt(arr, val, at, len) { arr.fill(val, at, at+len); } function charToBinary(char) { var bin = char.charCodeAt(0).toString(2); return new Array(9 - bin.length).join('0') + bin; } b.fill(-1.0); function writeBinary(offset, binary) { if (!binary) { binary = '00000000'; } var data = binary.split(''); // Bit preamble fillAt(b, 1.0, offset+4, 2); fillAt(b, 1.0, offset+300, 2); // Data data[0] === '1' && fillAt(b, 1.0, offset+304, 2); data[1] === '1' && fillAt(b, 1.0, offset+308, 2); data[2] === '1' && fillAt(b, 1.0, offset+312, 2); data[3] === '1' && fillAt(b, 1.0, offset+316, 2); data[4] === '1' && fillAt(b, 1.0, offset+320, 2); data[5] === '1' && fillAt(b, 1.0, offset+324, 2); data[6] === '1' && fillAt(b, 1.0, offset+328, 2); data[7] === '1' && fillAt(b, 1.0, offset+332, 2); // Bit postamble fillAt(b, 1.0, offset+336, 2); fillAt(b, 1.0, offset+632, 2); return offset+632; } function writeString(str) { var chars = str.split(''); var lastOffset = 0; for(var i = 0; i < chars.length; i++) { var char = chars[i]; var bin = charToBinary(char); lastOffset = writeBinary(lastOffset, bin); } } // Stream start fillAt(b, 1.0, 0, 2); writeString('abcdefghijklmnopqrstuvwxyz'); source = audioContext.createBufferSource(); source.buffer = buffer; source.connect(gainNode); gainNode.connect(audioContext.destination); source.start();
Espruino Receiver:
let readBits = false; let bits = []; function handlePulse(e) { const diff = e.time - e.lastTime; //console.log(diff); if (diff > 1.0 || isNaN(diff)) { if (readBits) { //console.log('stop reading bits'); readBits = false; } return; } const zeroes = (diff.toFixed(4) * 10000).toFixed(1); if (zeroes > 50) { if (readBits) { //console.log('stop reading bits'); readBits = false; bits.pop(); //console.log(bits); var str = bits.join(''); var num = parseInt(str, 2); var chr = String.fromCharCode(num); console.log(chr); bits = []; } else { //console.log('start reading bits'); readBits = true; } return; } if (readBits) { //console.log(diff); //console.log(zeroes); for(var i = 0; i < zeroes; i++) { bits.push(0); } bits.push(1); } } function onInit() { pinMode(A5, 'input_pullup'); setWatch(handlePulse, A5, { repeat: true, edge: 'rising' }); }
So now my question @Gordon, is how do I reverse this? i.e generate sound on Espruino. I'm guessing I want to just be doing digitalWrite to the pin I have wired to my headphone socket, can I reuse any of the code I have or should I start again?
Hi @Gordon,
What's the best way (given your experience) of working out which other STM chips Espruino is relatively simple to port to? Given that WiFi works on an STM I'm assuming there is compatibility across "some" of their chips...
Currently looking at https://www.mouser.co.uk/datasheet/2/389/stm32f479ai-956241.pdf as a bit of blue-sky thinking, mostly to get access to a MIPI-DSI Host.
Cheers,