-
-
@cool_acid: My ESP boards worked fine with the shim without any cap. Using the example. Except that the web server will get stuck if more than one request comes in at the same time. And of course the web client will get stuck after doing about 300 requests, most of the time. I have some auto-reset code catching that condition. None of that is the problem of the Pico, I am sure. The ESPs are notorious for these kinds of things.
But more general, in my experience those ESP boards are divas. They are cheap in more than one way. Sometimes they just don't work. Mine won't work with anything else than the Pico. For whatever reason, I don't know. Power? TX lines too long? No idea. Maybe yours just does not work. Do you have a second one to try?
-
While I initially also proposed Blowfish, I now think that maybe due to limited resources XXTEA is a better choice.
As a test, I implemented a C library which can be used to encrypt / decrypt strings using XXTEA. The code consumes roughly 1500 bytes. A test with encoding 10000 strings of 1000 bytes each took about 20 seconds, leading to about 500 KB per second encoding speed - decoding should be the same. That sounds pretty nice for me.
-
@Gordon - I reflashed the board with the newest version and it now works like a charm. Thanks for the fast fix! And glad, that I was not totally mistaken about the internal works of Espruino :-).
@allObjects - Yes, the LPC 810 is an awesome little board. I did not have a reason to play around with the pattern matching engine, sorry.
-
@Gordon - I checked the pulse example you gave above and it does work for me.
@allObjects - Thanks for checking the data sheet. I did not check it myself, because the example suggested, that this could work. And for example the AVR Attiny allows a deep sleep but will maintain the pin values. Also for example the NXP LPC 810 which I often use as a barebones chip has a power mode which has very low consumption but still drives the IO pins.
In any case, as written above, I tried the following as well:
function onInit() { setInterval(function() { setDeepSleep(false); digitalWrite(LED2, true); setTimeout(function() { digitalWrite(LED2, false); setDeepSleep(true); }, 100); }, 1000); setDeepSleep(true); }
If that would work, then I could achieve what I need. But it does not work either. Internally I would assume it does work because the pulse thing does work and it would have to disable the deep sleep according to your finding in the data sheet to be able to drive the pin.
BTW: Although you can actually see the visual difference between a 3ms LED pulse and a 20ms LED pulse (the 20ms is much brighter), I did use the oszi as written in the original post to find out the time.
For the interrupt driven operation: I think that's what @Gordon wants to make you believe :-). I don't think it is actually the case. In fact I believe it cannot be done. The way it usually works is that after initialization of the MCU, the processor then goes into a sort of main function which starts an endless loop. It will sleep in that loop until an interrupt occurs. In the interrupt handler it will have a very short routine which schedules some event. Then the loop in main wakes up and will handle the event. Then it goes to sleep again. I guess that's also why the documentation says that the deep sleep will come into effect when the current JavaScript execution is finished. That's when it returns to the main loop. Then it can sleep.
If you would do everything in the interrupt then all other interrupts would be blocked and that would be bad for the IO timing if you do something which is longer than a few microseconds... And I wrote I believe it cannot be done in that pure way, because the loop is actually needed. Otherwise the CPU would crash (I believe). The least you need to have is something like "while(1) __WFI;".
-
@allObjects: I don't think it is so natural, that putting the CPU in deep sleep mode switches off the outputs. With other MCUs I used before, this does not happen.
In any case, the reproduction case I mentioned is just that: A reproduction case. I was using a much longer sleep and then sent out a radio packet using the NRF24 module. That did not work, that's why I tried it with the LED and found out that it does not work either. What I also tried was to use "setDeepSleep(0)" inside the interval timer and switch it on again when the LED was switched off. That did not work either.
-
@tim, is there any specific reason why you want to use Bluetooth? As Gordon wrote, Bluetooth is nice and easy for connecting the Pico to a smartphone. Connecting two Picos is more tricky.
For connecting two Picos, I personally would maybe use a NRF24 with each Pico. Probably cheaper, can have better range and I think it is easier. And supported by a Pico library. Just a thought...
-
-
-
Hi,
I have a problem with the setDeepSleep. My understanding is that it should work on the Espruino Pico. Is this correct?
It does lead to weird effects for me. Basically I am using the following snippet from the power tutorial (with different constants):
setInterval(function() { digitalWrite(LED1, 1); setTimeout(function () { digitalWrite(LED1, 0); }, 5000); }, 10000); setDeepSleep(1);
The code works fine when connected to USB (my understanding is that deep sleep is disabled in that case anyway). It does not work when connected to a battery. Instead of blinking for 5 seconds every 10 seconds, it blinks every 10 seconds for like 3 ms (measured by monitoring the current consumption with an oscilloscope).
If I remove the setDeepSleep, then it works fine even with a battery - albeit with a lot higher power consumption, of course. I monitor the battery voltage and stays constant at about 4 V (Li-Ion).
Am I doing something wrong?
Thanks!
-
-
Very cool. I tested it and it works very nicely! Thanks very much! This way we have the best of both worlds.
The only thing I might do differently is to let E.hwRand() return a long int. This way you would not get signed values back but always unsigned. Signed random values are a bit unusual I would say. But it does not really matter much.
Being able to load C stuff directly would also be very cool. Although it is not too difficult to compile your own version - the documentation is very good...
-
It all depends... on the intended purpose... for games/rolling dices: absolutely useless, for regression testing with values covering a range: perfect.
100% agree. That's why in C there is always a seed for the standard random generator. So it allows you to do both - and even for regression testing one might want to use different sequences just to be sure that the one sequence there is is not a lucky one... I never understood why JavaScript does not have it.
A few Javascript lines based on your observations, could that become a 95% solution?
I guess the lines above are good enough for that purpose. Either as it is or we could put this into a JavaScript module. Not sure. Do you have any opinion? For my purposes, the C version is what I want. I will certainly keep it around and use it, even if it is not integrated.
-
Hi,
here is a first prototype of the RNG as a C module:
\#include "jswrap_rng.h" // We need the declaration of the jswrap_rng_random function \#include "jsinteractive.h" // Pull in the jsiConsolePrint function // Let's define the JavaScript class that will contain our `random()` methods. We'll call it `RNG` /*JSON{ "type" : "class", "class" : "RNG" }*/ // Now, we define the `jswrap_rng_random` to be a `staticmethod` on the `RNG` class /*JSON{ "type" : "staticmethod", "class" : "RNG", "name" : "random", "generate" : "jswrap_rng_random", "return" : ["JsVar","The random number or NAN, if it is not supported on the platform."] }*/ // Now, we define the `jswrap_rng_random_long` to be a `staticmethod` on the `RNG` class /*JSON{ "type" : "staticmethod", "class" : "RNG", "name" : "random_long", "generate" : "jswrap_rng_random_long", "return" : ["JsVar","The random number or NAN, if it is not supported on the platform."] }*/ // TODO: We need a better way to pull this in! This will not work on all boards. And we need // to make the jshAnalogRead function non-static where it is defined. extern int jshAnalogRead(JsvPinInfoAnalog analog, bool fastConversion); static int get_bit() { jshDelayMicroseconds(10); int v = jshAnalogRead(JSH_ANALOG1 | JSH_ANALOG_CH17, false); // It seems the lower 4 bits are always zero. v >>= 4; v &= 1; return v; } static long long rng_random() { \#if defined(STM32F1) || defined(STM32F4) // enable sensor ADC_TempSensorVrefintCmd(ENABLE); long long sum = 0; int s; int v1 = get_bit(); for (s = 0; s < 32; s++) { int v2 = get_bit(); sum <<= 1; if (v1 != v2) sum++; v1 = v2; } // disable sensor ADC_TempSensorVrefintCmd(DISABLE); return sum; \#else return NAN; \#endif } JsVar *jswrap_rng_random_long() { \#if defined(STM32F1) || defined(STM32F4) long long v = rng_random(); return jsvNewFromLongInteger(v); \#else return jsNewFromFloat(NAN); \#endif } JsVar *jswrap_rng_random() { \#if defined(STM32F1) || defined(STM32F4) long long v = rng_random(); double value = ((double)(v)) / 4294967296.0; return jsvNewFromFloat(value); \#else return jsNewFromFloat(NAN); \#endif }
Seems to work fine. But there are some flaws: Namely it pulls in some function from the hardware abstraction layer. I had to make the function non-static there. I am not sure what the best way would be to do this. Add the function to the hardware layer itself? Add a function which takes the analog reading as an int?
-
Hi allObjects,
Math.random() is not random at all, because it will always create the same sequence after rebooting. So that's not really helpful at all. Gordon wrote he will add the possibility to seed it. That's a first step. The second is a hardware based random number generator which can be used to produce a seed for it which is truly random.
As for the diodes: Yes, that's pretty much the idea. But in my experience just taking the analog reading of a diode as such won't be enough. You need to collect the least significant bits of multiple readings to get something less predictable. So instead of letting everyone write the code and mess around with diodes, there can be a library and it can be based on the analog reference instead of diodes, so no external parts needed at all.
I tried to find out if the analog reference is random enough to give a good seed. Which it apparently is - at least good enough for me.
-
-
Okay, I did a test with 10000 samples between 0..1. The mean was 0.51 (expected is of course 0.5 for a uniform distribution), the variance was 0.086631417 (expected variance is 0.083333333). I did a Kolmogorov-Smirnov test (I hope that I got it right). The maximum was 0.032498016, that should also be fine (between 0.07089 and 1.5174). Also optically the numbers look good. That was only with the analog reference.
I am no expert by any means, and I would not bet my life on it. But for me for anything except hard cryptography it should be fine.
-
Thanks, the seed would be a great start!
As for the RNG: I let it run for a while and the distribution looks okay - superficially. I am thinking about generating a bunch of random numbers and dumping them to a file. Then I could put them into a statistical test on the PC to see how good it is. But it might be dependent on the board and on the power supply. So it does not necessarily apply to all situations. But the general principle seems to be sound.
I tried the analog inputs as well, they seem to give the same results, pretty much. In my first version, you could select the input. The temperature also looks like a great idea! In addition, as mentioned the time since the startup could be used as an additional source.
If there is interest, I could put that in a library. I would then use the temperature and time as well to collect enough randomness.
-
Hi,
I need a random number generator for a project. Just found out that Math.random() always returns the same sequence after a reboot, making it not usable in my case. Especially because it is not possible to seed it. I want something less predictable. I guess that's the case in many applications, for example dice based games (you do not want to have the same game again and again after starting up), or for encryption when controlling something over radio.
First question: Would it make sense to allow to seed Math.random()? That would not force everyone who wants unpredictable randomness to implement their own RNG.
As this is not possible right now, I set out to implement something more random. After finding out that the MCU does not have the hardware random number generator some of the STM32F4 do have, I hacked together a little hardware based random number generator; similar to one which some people use on Arduinos.
It looks like this:
function random() { var sum = 0; var v1 = Math.floor(E.getAnalogVRef() * 100000000000) % 2; for (var s = 0; s < 32; s++) { sum *= 2; var v2 = Math.floor(E.getAnalogVRef() * 100000000000) % 2; if (v1 == v2) sum++; } return sum; }
It uses the least significant bits of the analog reference as a source of random bits. Note that the output seemed to be a bit biased (more 0s than 1s). The "if (v1==v2) is for whitening the random bits to remove that bias. It looks pretty good after that.
It is pretty slow but also pretty random - at least with my board when powered over USB. Have to try it with a battery to see how it behaves there. While I would not necessarily use it for hard cryptography, it is better than having to use the same sequence over and over again. It might also be interesting to couple it with the elapsed time to add more randomness.
Is this something which should be added to Espruino? I could also make a C module out of it, would be much faster. Maybe it would also be useful to use it only as a source for a random seed for Math.random - if seeing is added.
Any thoughts?
Stevie
@user54159, sure. But it's not really much. I guess Gordon will do a much better version at some point. This was more for experimentation, quickly hacked together. Due to the fact that xxtea needs to have the data with a size of multiples of 4, this version can only treat strings which do not contain the 0 character. I use it as a padding and also to detect end of string when decoding.
To include in the makefile put the following before "endif # BOOTLOADER":
Then you will be able to write something like this in JS:
The key needs to be exactly 16 characters, the data can be from 1 to 1024 bytes, because it will be copied to a char buffer.