2015-06-10 17:29:56 -04:00
|
|
|
General information about the WiPy
|
|
|
|
==================================
|
|
|
|
|
2015-10-14 06:32:01 -04:00
|
|
|
No floating point support
|
|
|
|
-------------------------
|
|
|
|
|
|
|
|
Due to space reasons, there's no floating point support, and no math module. This
|
|
|
|
means that floating point numbers cannot be used anywhere in the code, and that
|
|
|
|
all divisions must be performed using '//' instead of '/'. Example::
|
|
|
|
|
2015-10-21 08:58:04 -04:00
|
|
|
>>> r = 4 // 2 # this will work
|
|
|
|
>>> r = 4 / 2 # this WON'T
|
2015-10-14 06:32:01 -04:00
|
|
|
|
|
|
|
Before applying power
|
|
|
|
---------------------
|
|
|
|
|
2016-10-10 08:22:39 -04:00
|
|
|
.. warning::
|
2015-10-14 06:32:01 -04:00
|
|
|
|
2016-07-31 19:52:00 -04:00
|
|
|
The GPIO pins of the WiPy are NOT 5V tolerant, connecting them to voltages higher
|
2016-10-10 08:22:39 -04:00
|
|
|
than 3.6V will cause irreparable damage to the board. ADC pins, when configured
|
2015-10-20 10:24:25 -04:00
|
|
|
in analog mode cannot withstand voltages above 1.8V. Keep these considerations in
|
2015-10-14 06:32:01 -04:00
|
|
|
mind when wiring your electronics.
|
|
|
|
|
2015-06-10 17:29:56 -04:00
|
|
|
WLAN default behaviour
|
|
|
|
----------------------
|
|
|
|
|
2016-10-10 08:22:39 -04:00
|
|
|
When the WiPy boots with the default factory configuration starts in Access Point
|
|
|
|
mode with ``ssid`` that starts with: ``wipy-wlan`` and ``key: www.wipy.io``.
|
2015-06-10 17:29:56 -04:00
|
|
|
Connect to this network and the WiPy will be reachable at ``192.168.1.1``. In order
|
|
|
|
to gain access to the interactive prompt, open a telnet session to that IP address on
|
|
|
|
the default port (23). You will be asked for credentials:
|
2015-07-28 17:50:22 -04:00
|
|
|
``login: micro`` and ``password: python``
|
2015-06-10 17:29:56 -04:00
|
|
|
|
2015-10-21 08:58:04 -04:00
|
|
|
.. _wipy_telnet:
|
|
|
|
|
2015-10-20 10:24:25 -04:00
|
|
|
Telnet REPL
|
|
|
|
-----------
|
|
|
|
|
|
|
|
Linux stock telnet works like a charm (also on OSX), but other tools like putty
|
2015-10-26 15:41:14 -04:00
|
|
|
work quite well too. The default credentials are: **user:** ``micro``, **password:** ``python``.
|
2015-10-20 10:24:25 -04:00
|
|
|
See :ref:`network.server <network.server>` for info on how to change the defaults.
|
|
|
|
For instance, on a linux shell (when connected to the WiPy in AP mode)::
|
|
|
|
|
|
|
|
$ telnet 192.168.1.1
|
|
|
|
|
2015-11-12 00:00:31 -05:00
|
|
|
.. _wipy_filesystem:
|
|
|
|
|
2015-10-20 10:24:25 -04:00
|
|
|
Local file system and FTP access
|
|
|
|
--------------------------------
|
2015-06-10 17:29:56 -04:00
|
|
|
|
|
|
|
There is a small internal file system (a drive) on the WiPy, called ``/flash``,
|
|
|
|
which is stored within the external serial flash memory. If a micro SD card
|
2015-10-20 10:24:25 -04:00
|
|
|
is hooked-up and mounted, it will be available as well.
|
2015-06-10 17:29:56 -04:00
|
|
|
|
2015-10-20 10:24:25 -04:00
|
|
|
When the WiPy starts up, it always boots from the ``boot.py`` located in the
|
|
|
|
``/flash`` file system.
|
2015-06-10 17:29:56 -04:00
|
|
|
|
2015-10-21 08:58:04 -04:00
|
|
|
The file system is accessible via the native FTP server running in the WiPy.
|
2015-06-10 17:29:56 -04:00
|
|
|
Open your FTP client of choice and connect to:
|
|
|
|
|
2015-10-20 10:24:25 -04:00
|
|
|
**url:** ``ftp://192.168.1.1``, **user:** ``micro``, **password:** ``python``
|
|
|
|
|
|
|
|
See :ref:`network.server <network.server>` for info on how to change the defaults.
|
|
|
|
The recommended clients are: Linux stock FTP (also in OSX), Filezilla and FireFTP.
|
|
|
|
For example, on a linux shell::
|
|
|
|
|
|
|
|
$ ftp 192.168.1.1
|
2015-06-10 17:29:56 -04:00
|
|
|
|
2015-10-20 10:24:25 -04:00
|
|
|
The FTP server on the WiPy doesn't support active mode, only passive, therefore,
|
|
|
|
if using the native unix ftp client, just after logging in do::
|
2015-10-14 06:32:01 -04:00
|
|
|
|
|
|
|
ftp> passive
|
|
|
|
|
2015-10-20 10:24:25 -04:00
|
|
|
Besides that, the FTP server only supports one data connection at a time. Check out
|
2015-10-14 06:32:01 -04:00
|
|
|
the Filezilla settings section below for more info.
|
|
|
|
|
2015-08-05 11:05:41 -04:00
|
|
|
FileZilla settings
|
|
|
|
------------------
|
|
|
|
Do not use the quick connect button, instead, open the site manager and create a new
|
|
|
|
configuration. In the ``General`` tab make sure that encryption is set to: ``Only use
|
|
|
|
plain FTP (insecure)``. In the Transfer Settings tab limit the max number of connections
|
|
|
|
to one, otherwise FileZilla will try to open a second command connection when retrieving
|
|
|
|
and saving files, and for simplicity and to reduce code size, only one command and one
|
|
|
|
data connections are possible. Other FTP clients might behave in a similar way.
|
|
|
|
|
2015-10-19 10:28:29 -04:00
|
|
|
.. _wipy_firmware_upgrade:
|
|
|
|
|
2015-08-05 11:05:41 -04:00
|
|
|
Upgrading the firmware Over The Air
|
|
|
|
-----------------------------------
|
|
|
|
|
|
|
|
OTA software updates can be performed through the FTP server. Upload the ``mcuimg.bin`` file
|
|
|
|
to: ``/flash/sys/mcuimg.bin`` it will take around 6s. You won't see the file being stored
|
2015-10-20 10:24:25 -04:00
|
|
|
inside ``/flash/sys/`` because it's actually saved bypassing the user file system, so it
|
|
|
|
ends up inside the internal **hidden** file system, but rest assured that it was successfully
|
|
|
|
transferred, and it has been signed with a MD5 checksum to verify its integrity. Now, reset
|
|
|
|
the WiPy by pressing the switch on the board, or by typing::
|
2015-08-05 11:05:41 -04:00
|
|
|
|
2015-10-21 08:58:04 -04:00
|
|
|
>>> import machine
|
|
|
|
>>> machine.reset()
|
2015-08-05 11:05:41 -04:00
|
|
|
|
2016-10-10 08:22:39 -04:00
|
|
|
Software updates can be found in: https://github.com/wipy/wipy/releases (**Binaries.zip**).
|
2015-10-19 10:28:29 -04:00
|
|
|
It's always recommended to update to the latest software, but make sure to
|
2015-10-20 10:24:25 -04:00
|
|
|
read the **release notes** before.
|
2015-10-19 10:28:29 -04:00
|
|
|
|
2015-10-26 18:50:24 -04:00
|
|
|
.. note::
|
|
|
|
|
|
|
|
The ``bootloader.bin`` found inside ``Binaries.zip`` is there only for reference, it's not
|
|
|
|
needed for the Over The Air update.
|
|
|
|
|
2015-10-21 08:58:04 -04:00
|
|
|
In order to check your software version, do::
|
|
|
|
|
|
|
|
>>> import os
|
|
|
|
>>> os.uname().release
|
|
|
|
|
|
|
|
If the version number is lower than the latest release found in
|
|
|
|
`the releases <https://github.com/wipy/wipy/releases>`_, go ahead and update your WiPy!
|
|
|
|
|
2015-10-26 18:50:24 -04:00
|
|
|
|
2015-10-21 08:58:04 -04:00
|
|
|
.. _wipy_boot_modes:
|
|
|
|
|
|
|
|
Boot modes and safe boot
|
|
|
|
------------------------
|
2015-06-10 17:29:56 -04:00
|
|
|
|
|
|
|
If you power up normally, or press the reset button, the WiPy will boot
|
2016-10-10 08:22:39 -04:00
|
|
|
into standard mode; the ``boot.py`` file will be executed first, then
|
2015-06-10 17:29:56 -04:00
|
|
|
``main.py`` will run.
|
|
|
|
|
2015-07-28 17:03:53 -04:00
|
|
|
You can override this boot sequence by pulling ``GP28`` **up** (connect
|
2015-07-14 15:39:07 -04:00
|
|
|
it to the 3v3 output pin) during reset. This procedure also allows going
|
|
|
|
back in time to old firmware versions. The WiPy can hold up to 3 different
|
|
|
|
firmware versions, which are: the factory firmware plus 2 user updates.
|
|
|
|
|
2015-10-21 08:58:04 -04:00
|
|
|
After reset, if ``GP28`` is held high, the heartbeat LED will start flashing
|
2015-07-14 15:39:07 -04:00
|
|
|
slowly, if after 3 seconds the pin is still being held high, the LED will start
|
|
|
|
blinking a bit faster and the WiPy will select the previous user update to boot.
|
2015-07-28 17:03:53 -04:00
|
|
|
If the previous user update is the desired firmware image, ``GP28`` must be
|
2015-07-14 15:39:07 -04:00
|
|
|
released before 3 more seconds elapse. If 3 seconds later the pin is still high,
|
|
|
|
the factory firmware will be selected, the LED will flash quickly for 1.5 seconds
|
|
|
|
and the WiPy will proceed to boot. The firmware selection mechanism is as follows:
|
|
|
|
|
|
|
|
|
2015-07-28 17:03:53 -04:00
|
|
|
**Safe Boot Pin** ``GP28`` **released during:**
|
2015-07-14 15:39:07 -04:00
|
|
|
|
|
|
|
+-------------------------+-------------------------+----------------------------+
|
|
|
|
| 1st 3 secs window | 2nd 3 secs window | Final 1.5 secs window |
|
|
|
|
+=========================+=========================+============================+
|
2015-08-05 11:05:41 -04:00
|
|
|
| | Safe boot, *latest* | | Safe boot, *previous* | | Safe boot, the *factory* |
|
2015-07-14 15:39:07 -04:00
|
|
|
| | firmware is selected | | user update selected | | firmware is selected |
|
|
|
|
+-------------------------+-------------------------+----------------------------+
|
|
|
|
|
2015-10-21 18:31:22 -04:00
|
|
|
On all of the above 3 scenarios, safe boot mode is entered, meaning that
|
2015-08-05 11:05:41 -04:00
|
|
|
the execution of both ``boot.py`` and ``main.py`` is skipped. This is
|
|
|
|
useful to recover from crash situations caused by the user scripts. The selection
|
2015-10-21 18:31:22 -04:00
|
|
|
made during safe boot is not persistent, therefore after the next normal reset
|
2015-08-05 11:05:41 -04:00
|
|
|
the latest firmware will run again.
|
2015-06-10 17:29:56 -04:00
|
|
|
|
2015-10-21 08:58:04 -04:00
|
|
|
The heartbeat LED
|
2015-06-10 17:29:56 -04:00
|
|
|
------------------
|
|
|
|
|
2015-10-21 08:58:04 -04:00
|
|
|
By default the heartbeat LED flashes once every 4s to signal that the system is
|
2015-10-19 09:19:34 -04:00
|
|
|
alive. This can be overridden through the :mod:`wipy` module::
|
2015-06-10 17:29:56 -04:00
|
|
|
|
2015-10-21 08:58:04 -04:00
|
|
|
>>> import wipy
|
|
|
|
>>> wipy.heartbeat(False)
|
2015-06-10 17:29:56 -04:00
|
|
|
|
|
|
|
There are currently 2 kinds of errors that you might see:
|
|
|
|
|
2015-10-26 15:41:14 -04:00
|
|
|
1. If the heartbeat LED flashes quickly, then a Python script (eg ``main.py``)
|
2015-06-10 17:29:56 -04:00
|
|
|
has an error. Use the REPL to debug it.
|
2015-10-21 08:58:04 -04:00
|
|
|
2. If the heartbeat LED stays on, then there was a hard fault, you cannot
|
2015-07-28 17:50:22 -04:00
|
|
|
recover from this, the only way out is to press the reset switch.
|
2015-06-10 17:29:56 -04:00
|
|
|
|
2016-05-03 05:48:20 -04:00
|
|
|
Details on sleep modes
|
|
|
|
----------------------
|
2016-05-03 05:26:55 -04:00
|
|
|
|
2016-05-03 05:48:20 -04:00
|
|
|
* ``machine.idle()``: Power consumption: ~12mA (in WLAN STA mode). Wake sources:
|
2016-05-03 05:53:57 -04:00
|
|
|
any hardware interrupt (including systick with period of 1ms), no special
|
|
|
|
configuration required.
|
2016-05-03 05:48:20 -04:00
|
|
|
* ``machine.sleep()``: 950uA (in WLAN STA mode). Wake sources are ``Pin``, ``RTC``
|
|
|
|
and ``WLAN``
|
2016-10-10 08:22:39 -04:00
|
|
|
* ``machine.deepsleep()``: ~350uA. Wake sources are ``Pin`` and ``RTC``.
|
2017-04-05 05:09:36 -04:00
|
|
|
|
|
|
|
Additional details for machine.Pin
|
|
|
|
----------------------------------
|
|
|
|
|
|
|
|
On the WiPy board the pins are identified by their string id::
|
|
|
|
|
|
|
|
from machine import Pin
|
|
|
|
g = machine.Pin('GP9', mode=Pin.OUT, pull=None, drive=Pin.MED_POWER, alt=-1)
|
|
|
|
|
|
|
|
You can also configure the Pin to generate interrupts. For instance::
|
|
|
|
|
|
|
|
from machine import Pin
|
|
|
|
|
|
|
|
def pincb(pin):
|
|
|
|
print(pin.id())
|
|
|
|
|
|
|
|
pin_int = Pin('GP10', mode=Pin.IN, pull=Pin.PULL_DOWN)
|
|
|
|
pin_int.irq(trigger=Pin.IRQ_RISING, handler=pincb)
|
|
|
|
# the callback can be triggered manually
|
|
|
|
pin_int.irq()()
|
|
|
|
# to disable the callback
|
|
|
|
pin_int.irq().disable()
|
|
|
|
|
|
|
|
Now every time a falling edge is seen on the gpio pin, the callback will be
|
|
|
|
executed. Caution: mechanical push buttons have "bounce" and pushing or
|
|
|
|
releasing a switch will often generate multiple edges.
|
|
|
|
See: http://www.eng.utah.edu/~cs5780/debouncing.pdf for a detailed
|
|
|
|
explanation, along with various techniques for debouncing.
|
|
|
|
|
|
|
|
All pin objects go through the pin mapper to come up with one of the
|
|
|
|
gpio pins.
|
|
|
|
|
|
|
|
For the ``drive`` parameter the strengths are:
|
|
|
|
|
|
|
|
- ``Pin.LOW_POWER`` - 2mA drive capability.
|
|
|
|
- ``Pin.MED_POWER`` - 4mA drive capability.
|
|
|
|
- ``Pin.HIGH_POWER`` - 6mA drive capability.
|
|
|
|
|
|
|
|
For the ``alt`` parameter please refer to the pinout and alternate functions
|
|
|
|
table at <https://raw.githubusercontent.com/wipy/wipy/master/docs/PinOUT.png>`_
|
|
|
|
for the specific alternate functions that each pin supports.
|
|
|
|
|
|
|
|
For interrupts, the ``priority`` can take values in the range 1-7. And the
|
|
|
|
``wake`` parameter has the following properties:
|
|
|
|
|
|
|
|
- If ``wake_from=machine.Sleep.ACTIVE`` any pin can wake the board.
|
|
|
|
- If ``wake_from=machine.Sleep.SUSPENDED`` pins ``GP2``, ``GP4``, ``GP10``,
|
|
|
|
``GP11``, GP17`` or ``GP24`` can wake the board. Note that only 1
|
|
|
|
of this pins can be enabled as a wake source at the same time, so, only
|
|
|
|
the last enabled pin as a ``machine.Sleep.SUSPENDED`` wake source will have effect.
|
|
|
|
- If ``wake_from=machine.Sleep.SUSPENDED`` pins ``GP2``, ``GP4``, ``GP10``,
|
|
|
|
``GP11``, ``GP17`` and ``GP24`` can wake the board. In this case all of the
|
|
|
|
6 pins can be enabled as a ``machine.Sleep.HIBERNATE`` wake source at the same time.
|
2017-04-05 06:05:04 -04:00
|
|
|
|
|
|
|
Additional Pin methods:
|
|
|
|
|
|
|
|
.. method:: machine.Pin.alt_list()
|
|
|
|
|
|
|
|
Returns a list of the alternate functions supported by the pin. List items are
|
|
|
|
a tuple of the form: ``('ALT_FUN_NAME', ALT_FUN_INDEX)``
|
2017-04-08 17:48:28 -04:00
|
|
|
|
|
|
|
Known issues
|
|
|
|
------------
|
|
|
|
|
|
|
|
Incompatible way to create SSL sockets
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
SSL sockets need to be created the following way before wrapping them with.
|
|
|
|
``ssl.wrap_socket``::
|
|
|
|
|
|
|
|
import socket
|
|
|
|
import ssl
|
|
|
|
s = socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_SEC)
|
|
|
|
ss = ssl.wrap_socket(s)
|