-
An Espruino can emulate a mouse http://www.espruino.com/USB. What's with the "opposite" direction?
Is it possible to connect a mouse to an Espruino and capture mouse events?
I would like to use some kind of 3D mouse or wacom tablet as input device.
-
Ok, that's a plan. I share your concern about the extra complexity and the missing acceptance while developing a module. There is still a switch in the build script for @compilation_level ADVANCED_OPTIMIZATIONS. A module developer has to rewrite his whole module code with me['property'] syntax and therefore only one module is using it. This special case could be removed with the new approach.
It will be really easy to add a small extern file with round about 10 lines and don't change the code at all. The modification to the build script will be minimal - I'll try to prove ;-) -
I'd imagine that your example of using var htu = exports.connect( null ); may cause some problems though. ...
Extern/usage files are handled differently by the optimizer. It's enough to reference the functions. First I thought a usage scenario is better readable but it's not.
htu.isMeasuring; htu.readTemperature; htu.getTemperature; htu.readHumidity; htu.getHumidity; htu.getCompensatedHumidity; htu.getDewPoint; htu.softReset; htu.getResolution; htu.setResolution; htu.isEndOfBattery; htu.isHeaterOn; htu.setHeaterOn; htu.getSerialNumer;
Also, when the modules themselves are minified, they get wrapped with (function() { ... })(), which allows the compiler to rename any non-exported functions/variables, even with simple optimisations.
I saw the wrapping in the build script. It's not nessecarry in advance mode anymore. It's even counterproductive. After wrapping, minifying and unwrapping the HTU21D module is a few bytes larger (in advanced mode). I will investigate it when the next steps are clear.
Is that what you're doing for your figures here? Last I checked, the difference in size was nowhere near as big as you're getting - there does seem to be a difference between the modules at espruino.com/modules/ and the figures you have...
I didn't try to cheat. I found that the difference between the current minified files on the website and my numbers in the posting was in the compiler settings and the (sometimes) missing wrapping in my build settings.
And I tricked myself: The minified version is even smaller, e.g. MCP9808:- Earlier posting: simple minified: 3745 bytes
- Earlier posting: advanced minified: 2427 bytes
- Website: 3429 bytes
- Now minified with advanced optimization: 1994 bytes (> 40% smaller)
I'm not quite sure how that'd be done, but it might be that just defining require as function require(x) { return modules[x]; } would be enough - the closure compiler is pretty smart.
I will try and report back. But it will take a few days. And without ensuring that every used module is "advanced optimization"-safe we cannot enabled advance optimization for whole programs.
What should be the next step? Perhaps selecting one module as an example, specify the exact steps, writing the extern file, customizing the build script, ...?
- Earlier posting: simple minified: 3745 bytes
-
I remember having lots of trouble making anything minified with advanced minification actually run - Have you checked that the code you're having it minify actually runs after going through advanced minification?
Yes, the minified code is working. But you are right. We should not enable advanced optimization blindly. Every module has to be examined and tested separately. This can be done step-by-step.
What kind of trouble do you mean? Did you use an extern/usage file? First I tried to avoid this additional file and - yes - also with JSDoc and Google annotation it never worked in all cases.
-
While minifying modules currently the Google closure compiler will be used with SIMPLE optimization (=default without the @compilation_level ADVANCED_OPTIMIZATIONS annotation).
Moray gave an example of using advance optimization while he was refactoring the BME module. → http://forum.espruino.com/conversations/277165/
There is still a little imperfection already stated: The basic rule is refer to anything you don't want minified as an indirect property reference, so me.property should be written as me['property'].
This blights the code a little bit and can be avoided be giving the closure compiler the knowledge which code you want to keep. Moray already mentioned the "extern" approach http://forum.espruino.com/comments/12636552/. A simple usage scenario (without parameters) would be enough. Here is an example of the HTU21D module:var htu = exports.connect( null ); var t1 = htu.RH_12_BITS_TEMP_14_BITS; var t2 = htu.RH_8_BITS_TEMP_12_BITS; var t3 = htu.RH_10_BITS_TEMP_13_BITS; var t4 = htu.RH_11_BITS_TEMP_11_BITS; htu.isMeasuring(); htu.readTemperature(); htu.getTemperature( null ); htu.readHumidity(); htu.getHumidity(); htu.getCompensatedHumidity( null, null ); htu.getDewPoint( null, null ); htu.softReset(); htu.getResolution(); htu.setResolution( null ); htu.isEndOfBattery(); htu.isHeaterOn(); htu.setHeaterOn( null ); htu.getSerialNumber();
Now you can leave all the module code and advanced optimization works fine. But from where should we take this usage code for every module?
- Write it manually
- Extract it from the code annotations
Google itself has an @export notation but then you have to use the Google Closure Library → not applicable.
Parse/Grep would be possible but it's a lot of work until reaching a stable version for all possible cases. - Using a precompiler like TypeScript. Type information is available and it's seems Google is enhancing the minifier with some TypeScript support. For me this is the most promising option because I write modules in TypeScript and the advantage of using TypeScript at all is huge. But I think many module developers do not share this opinion - up to now. We'll see us in one year. ;-) But there is currently no out-of-the-box solution.
Currently I prefer 1) because it's straightforward and easy realizable and additionally leaves option 2) and 3) open.
Later it would be possible to enable advanced optimization in the IDE. This would be really great to remove all unused code during
save()
.What do you think about adding a simple extern/usage file for every module and compile the modules with advanced optimization? This would not be a huge one-step-solution. Every module can decide by itself:
- No extern file available → simple optimization
- extern file available → advanced optimization
A few numbers for the motivation behind:
- HTU21D.js: 14391 bytes, simple minified: 3802 bytes, advanced minified: 2400 bytes
- MLX90614.js: 4867 bytes, simple minified: 1714 bytes, advanced minified: 1166 bytes
- MAG3110.js: 8219 bytes, simple minified: 2547 bytes, advanced minified: 1542 bytes
- MCP9808.js: 12928 bytes, simple minified: 3745 bytes, advanced minified: 2427 bytes
Code sizes shrink about 30% to 40% when switching from simple to advanced optimization.
BTW: The Google webservice is slow with ADVANCED_OPTIMIZATIONS and denied after using too often. I wrote a local build script. It uses exactly the same directory/file convention so no customization is required. It's faster and no additional installation except Java is required (Google Closure Compiler is a Java program). I would make it available if somebody is interested...
And that could be the roadmap:
- Write or generate an espruino_extern.js file, still mentioned http://forum.espruino.com/comments/12636552/
- Create a file XXX_extern.jsfile for every module step-by-step
Any thoughts?
- Write it manually
-
I bought a watch very similar to this one mentioned by Gordon and want to read out the firmware via SWD (with stm32f4-discovery). But I couldn't find SWDCLK.
The cpu is DA14580 (datasheet) from Dialog Semiconductor. Everything (e.g., SWDIO) is labeled well - but SWDCLK is missing. I can't believe it.
Does anybody have an idea about the meaning of pins in the picture?
-
This is funny! I've got the version with the cpu from Dialog semiconductor: DA14580 (50k RAM).
- Can I determine whether they use flash or otp?
- I cannot recognise the acceleration chip. @Gordon I couldn't see the kx022 on your pictures?
- Would it be possible to port Espruino to the Dialog cpu (Cortex M0)?
- Can I determine whether they use flash or otp?
-
Just for completeness: The MLX90614 would not be the right sensor for measuring the temperature of a soldering tip. The sensor does not measure the maximum temperature but integrates the emission over a certain angle (70°-80°). Thus it is better for getting the temperature of larger things like an oven. Otherwise you have to put the sensor very near to the object like a medical ear thermometer.
-
Yay, it works with
I2C3.setup( { scl: A8, sda: B4 } );
on the pico. Thank you!!I've checked the other I2C-pins too:
I2C1.setup( { scl: B6, sda: B7 } ); // not working
2.I2C1.setup( { scl: B8, sda: B9 } ); // not working
3.I2C2.setup( { scl: B10, sda: B3 } ); // working
4.I2C3.setup( { scl: A8, sda: B4 } ); // working
But USB is always connected. Is there really no difference between I2C1 and the I2C2 or I2C3?
-
Ooh, it works with the original Espruino board:
I2C1.setup( { scl: B6, sda: B7 } ); function start() { I2C1.writeTo( { address: 0x5a, stop: false }, 0x06 ); var d = I2C1.readFrom( 0x5a, 3 ); var temp = ((d[1] << 8) + d[0]) * 0.02 - 273.15; // formula from datasheet console.log( "Temperature = " + temp + "°C" ); } setTimeout( start, 250 ); // Sensor available 1/4 sec after POR
Are the boards different related to the power supply or the i2c setup?
-
-
Currently I'm developing an Espruino module for MLX90614 - an infra red thermometer I2C sensor.
https://learn.adafruit.com/using-melexis-mlx90614-non-contact-sensors/overview
It's nearly complete but I have strange problems with the initialisation. I figured out that the sensor always works when the power supply will be switched on after I2C1.setup(..)-call. So I have connected Vin of the sensor with B3 to simulate switching on/off programmatically.
The following code works without any problems:I2C1.setup( { scl: B6, sda: B7 } ); digitalWrite( B3, 1 ); // Power on after I2C1.setup(..) function start() { I2C1.writeTo( { address: 0x5a, stop: false }, 0x06 ); // repeated start I2C requests var d = I2C1.readFrom( 0x5a, 3 ); var temp = ((d[1] << 8) + d[0]) * 0.02 - 273.15; // formula from datasheet console.log( "Temperature = " + temp + "°C" ); } setTimeout( start, 250 ); // Sensor available 1/4 sec after POR
But now strange things happen. The following code works only one or two times after connecting the USB cable and then never again.
digitalWrite( B3, 1 ); // Power on before I2C1.setup(..) I2C1.setup( { scl: B6, sda: B7 } ); function start() { I2C1.writeTo( { address: 0x5a, stop: false }, 0x06 ); var d = I2C1.readFrom( 0x5a, 3 ); var temp = ((d[1] << 8) + d[0]) * 0.02 - 273.15; // formula from datasheet console.log( "Temperature = " + temp + "°C" ); } setTimeout( start, 250 ); // Sensor available 1/4 sec after POR
Instead of
Temperature = 22.37°C
an exception is thrown:Uncaught InternalError: Timeout on I2C Write BUSY at line 14 col 51 i2c.writeTo( { address: 0x5a, stop: false }, 0x06 ); ^ in function called from system
I have no ideas anymore how to find the cause. I don't have a memory oscilloscope and can't say what happens during "I2C1.setup(..)".
Does anybody have an idea how I could continue...? -
The default bitrate is actually 50000 (at least on proper Espruino boards)... Which one are you using?
Good to know. I thought the default bitrate were higher. I'm using a classic and different pico boards. So it is unnecessary in my case to check the bitrate if nobody increase it explicitly. Ok, thanks.
i2c._options.bitrate
looks more like an internal API. I would prefer a documented getBitrate() method but that's only my viewpoint. -
I think the usage of
clearInterval()
(with no arguments) is dangerous in general and should be avoided (except while playing in the Web IDE). Every module could usesetInterval/setTimeout
internally (and some do). I still like thatclearInterval()
does not remove the timer from setWatch anymore because it is a little unexpected.Or is there any safe usecase for clearInterval(void) which I don't see?
-
Currently I'm developing an Espruino module for an I2C sensor which is not able to run with the default bitrate of 400 kHz.
I want to ensure that nobody fall into the same trap to forget the bitrate parameter in I2C.setup(). I know: "Read the datasheet carefully ...". But better would be an automatic check with a human readable hint about the wrong usage.
Is it possible to get the bitrate of an I2C instance to check the correct usage in the connect()-methods or directly in the constructor function of i2c-sensors, e.g.
exports.connect = function ( /*=I2C*/i2c ) { var br = i2c.getBitrate(); if (br && (br < 10000 || br > 100000)) { throw new Error( "The maximum clock frequency is 100 kHz and the minimum is 10 kHz." ); } return new MLX90614( i2c ); };
-
- "Answer" from http://www.espruino.com/MicroBit → No, no USART.
- "Answer" from https://en.wikipedia.org/wiki/Micro_Bit → Yes, serial I/O.
Does anybody know whether it will be possible to connect a sensor with a serial interface (+3.3V voltage level) ?
- "Answer" from http://www.espruino.com/MicroBit → No, no USART.
-
@verdeimpacat
It is unnecessary to call//soft reset is required before use of HTU21D htu.softReset();
I put this call to the constructor of HTU21D which will be called during "require('HTU21D').connect(…);". Soft Reset is recommended in the data sheet, so nobody can forget it.
function HTU21D( i2c ) { … this.softReset(); // Soft reset is recommended at start according to the datasheet. }
-
I made a few experiments with two original and two 3rd party nunchucks. I had no problem with the 3rd party nunchucks in principle. The software module works with both. But the cheaper ones will die earlier. They do not have the same hardware protection as the original ones.
For instance when I put the connector in the wrong direction one clone was immediately dead. The original nunchuck pulls the voltage down, probably with a diode.
Maybe this is the reason for the negative reviews of the cheaper nunchucks?Another point: Some older Arduino libraries use "encrypted" communication which is not supported by the cheap nunchucks. You can recognize this by the initialization sequence 0x40 0x00. The unencrypted communication starts with 0xF0 0x55.
- There is a little bug in the current espruino module. The second last sensor value will be returned by read() not the last one. That's why the first read always gives wrong data.
- The range of values from the joystick and the neutral point differ strongly between several nunchucks. I added a few calibration methods (zero, maxX, maxY) for normalization and the results look good.
After documenting I will make a pull request within the next few days to fix the two points.
But I have questions too:
- What is the correct English name? Nunchuck or Nunchuk
- The javascript file is wii_nunchuck.js. The documentation lies in Wii.md. Could I rename this file to wii_nunchuck.md?
- There is a little bug in the current espruino module. The second last sensor value will be returned by read() not the last one. That's why the first read always gives wrong data.
-
Thank you for the hints. First I thought it would be an Espruino/JavaScript API question and totally forgot to think about the electrical part.
The I²C specification says that the minimal pull-up is a little less than 1k with Vdd=3.3V and the maximum value depends on bus capacitance. Many breakouts have 4.7k so it's possible to use four devices (with pullups) in parallel without breaking the spec.
There is detailed application note from TI: http://www.ti.com/lit/an/slva689/slva689.pdf
On the other side I have to use a much lower value than the typical 40k MCU-internal resistors for 400kHz - I understand now.
So I found my stability problem with the MCP9808 http://www.espruino.com/MCP9808. My sentence
The sensor can handle bitrates up to 400000 but I had stability problems with this.
can be removed from the documentation.
BTW: Why are there "°"s instead of ° on the website?
Again, thanks for the Tips.
-
Hi,
I'm using the temperature and humidity I²C sensor HTU21D in my current experiments. The bought Sparkfun HTU21D breakout had no prewired pull-up resistors on SCL or SDA. They are on the board but initial not connected. To enable I could bridge a solder jumper. Ok, long background...I would prefer to use the MCU-internal pull-ups and tried the following code which does not work:
pinMode( B8, "input_pullup" ); pinMode( B9, "input_pullup" ); I2C1.setup( {scl: B8, sda: B9 } );
Is this possible to use the MCU-internal pull-ups with i2c or can they only be used for simple input pins?
-
Hi, I'm using an adapted version of i2cdetect for my own i2c experiments. Maybe it is useful for somebody else:
function scanI2c( i2c, first, last ) { if (typeof first === "undefined") { first = 0x03; } if (typeof (last) === "undefined") { last = 0x77; } print( " 0 1 2 3 4 5 6 7 8 9 a b c d e f" ); for (var upper = 0; upper < 8; ++upper) { var line = upper + "0: "; for (var lower = 0; lower < 16; ++lower) { var address = (upper << 4) + lower; // Skip unwanted addresses if ((address < first) || (address > last)) { line += " "; continue; } try { i2c.readFrom( address, 1 ); line += (address + 0x100).toString( 16 ).substr( -2 ); line += " "; } catch (err) { line += "-- "; } } print( line ); } } // Usage I2C1.setup( {scl: B8, sda: B9} ); scanI2c( I2C1, 0x03, 0x2f );
Output - first line is not aligned correctly.
0 1 2 3 4 5 6 7 8 9 a b c d e f 00: 03 04 05 06 07 -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
What would be the right place for such a code snippet?
- Too special → don't share
- Own module: require("i2cdetect").scan()
- https://gist.github.com/
- ???
It takes quite a long time to scan all addresses. Is it possible to decrease the timeout somehow?
- Too special → don't share
-
After you mentioned an encoder with four callback per click I looked for different types of encoders: The topic is more complicated than I thought.
- There are encoders without any notch/click. The current implementation would be the best for these types.
- There are encoders with click and the switches toggle BETWEEN the stable positions. This is the most common case I think.
- There are encoders where one switch is at the stable click position. Here the pins are not symmetric and must be handled differently. Perhaps your last mentions encoder is of this type? Do you know the name of your 4-steps-per-click encoder?
- ??? Maybe there are even more?
Espruino is such a great platform so we should supported each type out of the box with simple parameterization and not choose one in favor of the others. The principle of a rotary encoder is the same only the state machine differs.
I have created a small pull request to initialize the current module correctly.
https://github.com/espruino/EspruinoDocs/pull/187 → Solution for 1)Next I will play a little bit with different rotary encoders. I will try to merge the current module code with the attached version and generalize the module. The current module behavior (+/-2) could then be the default one. Existing clients will not be broken. And the documentation should point to the parameterization possibilities.
What do you think? Should I try this?
- There are encoders without any notch/click. The current implementation would be the best for these types.
-
Hello,
I tried to use the Encoder module with a rotary encoder (http://www.amazon.com/dp/B00HSX9ZB2).var step = 0; require("Encoder").connect(A1,A2,function (direction) { step += direction; print(step); });
step will be incremented/decremented by 2 on every notch. This is not expected when looking at the api but understandable when looking at the implementation. The state machine 00 → 01 → 11 → 11 → .. calls onChange() also in the instable states 01 and 10.
This is academically correct for general gray codes. But I think that is not the intended behavior for supporting an incremental rotary encoder because client code will now have to skip every second callback. What is your opinion? Who is using this module? How do you deal with these circumstances? Do you use the "Encoder" module for something other than rotary encoders?
I made an adaption with a more "rotary encoder" behavior - it's attached. If desired I could make a pull request with some additional debounce logic. Debouncing is now possible because of the internal "forbidden" states.
BTW there is a small bug in the initialization code of the original module. The first step will not be detected correctly. I fix it if the attached new code should not be used.
Is it nearly impossible because of some constraints (memory, ..) or is it just not implemented until now?
If latter, is it possible to estimate the effort when using some existing library from STM e.g. http://www.st.com/web/catalog/tools/FM147/CL1794/SC961/SS1743/PF257882?