@@ -50,19 +50,20 @@ mode is enabled by specifying the `-f`option.
...
@@ -50,19 +50,20 @@ mode is enabled by specifying the `-f`option.
-**Compact relocatable**. This is selected by the `-f` option. Here the compiler compresses the compiled binary so that image is small for downloading over Wifi/WAN (e.g. a full 64Kb LFS image is compressed down to a 22Kb file.) The LVM processes such image in two passes with the integrity of the image validated on the first, and the LFS itself gets updated on the second. The LVM also checks that the image will fit in the allocated LFS region before loading, but you can also use the `-m` option to throw a compile error if the image is too large, for example `-m 0x10000` will raise an error if the image will not load into a 64Kb regions.
-**Compact relocatable**. This is selected by the `-f` option. Here the compiler compresses the compiled binary so that image is small for downloading over Wifi/WAN (e.g. a full 64Kb LFS image is compressed down to a 22Kb file.) The LVM processes such image in two passes with the integrity of the image validated on the first, and the LFS itself gets updated on the second. The LVM also checks that the image will fit in the allocated LFS region before loading, but you can also use the `-m` option to throw a compile error if the image is too large, for example `-m 0x10000` will raise an error if the image will not load into a 64Kb regions.
-**Absolute**. This is selected by the `-a <baseAddr>` option. Here the compiler fixes all addresses relative to the base address specified. This allows an LFS absolute image to be loaded directly into the ESP flash using a tool such as `esptool.py`.
-**Absolute**. This is selected by the `-a <baseAddr>` option. Here the compiler fixes all addresses relative to the base address specified. This allows an LFS absolute image to be loaded directly into the ESP flash using a tool such as `esptool.py`. _Note that the new NodeMCU loader uses the `-f` compact relocatable form and does relocation based on the Partition Table, so this option is deprecated and will be removed in future releases.
These two modes target two separate use cases: the compact relocatable format
These two modes target two separate use cases: the compact relocatable format
facilitates simple OTA updates to an LFS based Lua application; the absolute format
facilitates simple OTA updates to an LFS based Lua application; the absolute format
facilitates factory installation of LFS based applications.
facilitates factory installation of LFS based applications.
Also note that the `app/lua/luac_cross` make and Makefile can be executed to build
Also note that the `app/lua/luac_cross` make and Makefile can be executed to build
just the `luac.cross` image. You must first ensure that the following options in
just the `luac.cross` image. You must first ensure that the following option in
`app/include/user_config.h`are matched to your target configuration:
`app/include/user_config.h`is matched to your target configuration:
```c
```c
//#define LUA_NUMBER_INTEGRAL // uncomment if you want an integer build
//#define LUA_NUMBER_INTEGRAL // uncomment if you want an integer build
//#define LUA_FLASH_STORE 0x10000 // uncomment if you LFS support
```
```
Note that the use of LFS and the LFS region size is now configured through the partition table.
Developers have successfully built this on Linux (including docker builds), MacOS, Win10/WSL and WinX/Cygwin.
Developers have successfully built this on Linux (including docker builds), MacOS, Win10/WSL and WinX/Cygwin.
@@ -226,7 +226,7 @@ Detailed instructions available in the image's README. As for available config o
...
@@ -226,7 +226,7 @@ Detailed instructions available in the image's README. As for available config o
### For LFS
### For LFS
1. In `app/include/user_config.h`uncomment`#define LUA_FLASH_STORE 0x10000` and adjust the size if necessary.
1. In `app/include/user_config.h`edit the line`#define LUA_FLASH_STORE 0x0` and adjust the size to that needed. Note that this must be a multiple of 4Kb.
2. Build as you would otherwise build with this image (i.e. see its README)
2. Build as you would otherwise build with this image (i.e. see its README)
[↑ back to matrix](#task-os-selector)
[↑ back to matrix](#task-os-selector)
...
@@ -238,24 +238,25 @@ _Note that this Docker image is not an official NodeMCU offering. It's maintaine
...
@@ -238,24 +238,25 @@ _Note that this Docker image is not an official NodeMCU offering. It's maintaine
A local copy of `luac.cross` is only needed if you want to compile the Lua files into an LFS image yourself and you are _not_ using Docker.
A local copy of `luac.cross` is only needed if you want to compile the Lua files into an LFS image yourself and you are _not_ using Docker.
### Windows
### Windows
Windows 10 users can install and use the Windows Subsystem for Linux (WSL). Alternatively all Windows users can [install Cygwin](https://www.cygwin.com/install.html)(only Cygwin core + **gcc-core** + **gnu make**). Either way, you will need a copy of the `luac.cross` compiler:
Windows users can compile a local copy of the `luac.cross` executable for use on a development PC. To this you need:
- To download the current NodeMCU sources (this [dev ZIP file](https://github.com/nodemcu/nodemcu-firmware/archive/dev.zip) or [master ZIP file](https://github.com/nodemcu/nodemcu-firmware/archive/master.zip)) and unpack into a local folder, say `C:\nodemcu-firmware`; choose the master / dev versions to match the firmware version that you want to use. If you want an Integer buld then edit the `app/includes/user_config.h` file to select this.
- You can either download this from Terry's fileserver. The [ELF variant](http://files.ellisons.org.uk/esp8266/luac.cross) is used for all recent Linux and WSL flavours, or the [cygwin binary](http://files.ellisons.org.uk/esp8266/luac.cross.cygwin)) for the Cygwin environment.
- Choose a preferred toolchain to build your `luac.cross` executable. You have a number of options here:
- Or you can compile it yourself by downloading the current NodeMCU sources (this [ZIPfile](https://github.com/nodemcu/nodemcu-firmware/archive/master.zip)); edit the `app/includes/user_config.h` file and then `cd` to the `app/lua/luac_cross` and run make to build the compiler in the NodeMCU firmware root directory. Note that the `luac.cross` make only needs the host toolchain which is installed by default.
- If you are a Windows 10 user with the Windows Subsystem for Linux (WSL) already installed, then this is a Linux environment so you can follow the [Linux build instructions](#Linux) below.
- A less resource intensive option which works on all Windows OS variants is to use Cygwin or MinGW, which are varaint ports of the [GNU Compiler Collection](https://gcc.gnu.org/) to Windows and which can both compile to native Windows executables. In the case of Cygwin, [install Cygwin](https://www.cygwin.com/install.html)(selecting the Cygwin core + **gcc-core** + **gnu make** in the install menu). In the case of MinGW you again only need a very basic C build environment so [install the MINGW](http://mingw.org/wiki/InstallationHOWTOforMinGW); you only need the core GCC and mingw32-make. Both both these create a **Cmd** prompt which paths in the relevant GCC toolchain. Switch to the `app/lua/luac_cross` and run make to build the compiler in the NodeMCU firmware root directory. You do this by rning `make` in Cygwin and `mingw32-make -f mingw32-Makefile.mak` in MinGW.
### macOS
- If you can C development experience on the PC and a version of the MS Visual Studio on your PC then you can also simply build the image using the supplied MS project file.
- Once you have a built `luac.cross` executable, then you can use this to compile Lua code into an LFS image. You might wish to move this out of the nodemcu-firmware hierarchy, since this folder hierarchy is no longer required and can be trashed.
TBD
1.`$ cd app/lua/luac_cross`
2.`$ make`
### Linux
### Linux
TBD
- Ensure that you have a "build essential" GCC toolchain installed.
- Download the current NodeMCU sources (this [dev ZIP file](https://github.com/nodemcu/nodemcu-firmware/archive/dev.zip) or [master ZIP file](https://github.com/nodemcu/nodemcu-firmware/archive/master.zip)) and unpack into a local folder; choose the master / dev versions to match the firmware version that you want to use. If you want an Integer buld then edit the `app/includes/user_config.h` file to select this.
- Change directory to the `app/lua/luac_cross` sub-folder
- Run `make` to build the executable.
- Once you have a built `luac.cross` executable, then you can use this to compile Lua code into an LFS image. You might wish to move this out of the nodemcu-firmware hierarchy, since this folder hierarchy is no longer required and can be trashed.
1.`$ cd app/lua/luac_cross`
### macOS
2.`$ make`
As for [Linux](#linux)
[↑ back to matrix](#task-os-selector)
[↑ back to matrix](#task-os-selector)
...
@@ -325,4 +326,45 @@ Once the LFS image file is on SPIFFS, you can execute the [node.flashreload()](.
...
@@ -325,4 +326,45 @@ Once the LFS image file is on SPIFFS, you can execute the [node.flashreload()](.
Do a protected call of this `_init` code: `pcall(node.flashindex("_init"))` and check the error status. See [Programming Techniques and Approachs](lfs.md#programming-techniques-and-approachs) in the LFS whitepaper for a more detailed description.
Do a protected call of this `_init` code: `pcall(node.flashindex("_init"))` and check the error status. See [Programming Techniques and Approachs](lfs.md#programming-techniques-and-approachs) in the LFS whitepaper for a more detailed description.
### Minimal LFS example
Below is a brief overview of building and running the simplest LFS-based system possible.
To use LFS, start with a version of NodeMCU with `LUA_FLASH_STORE` set in `app/include/user_config.h`, and load it on the ESP8266 in the usual way (whatever that is for your set up).
Then build an LFS file system. This can be done in several ways, as discussed above; one of the easiest is to use `luac.cross -f -o lfs.img *lua` on the host machine. The file [lua_examples/lfs/_init.lua](https://github.com/nodemcu/nodemcu-firmware/tree/dev/lua_examples/lfs/_init.lua) should definitely be included in the image, since it's the easiest way of registering the LFS modules. The `lfs.img` file can then be downloaded to the ESP8266 just like any other file.
The next step is to tell the ESP8266 that the LFS file system exists. This is done with eg. [node.flashreload("lfs.img")](../modules/node/#nodeflashreload), which will trigger a reset, followed by [node.flashindex("_init")()](../modules/node/#nodeflashindex) to register the modules; logging into the esp8266 and running the following commands gives an overview of the command sequence, given a main.lua file consisting of the line `print("LFS main() module")`
```
>
> node.flashreload("lfs.img")
-- flashreload() triggers a reset here.
> print(LFS)
nil
> node.flashindex("_init")()
-- LFS is now initialised.
> print(LFS)
table: 3fff06e0
-- List the modules in the LFS.
> print(LFS._list)
table: 3fff0728
> for k,v in pairs(LFS._list) do print(k,v) end
1 dummy_strings
2 _init
3 main
-- Call the LFS main() module.
> LFS.main()
LFS main() module
>
```
Note that no error correction has been used, since the commands are intended to be entered at a terminal, and errors will become obvious.
Then you should set up the ESP8266 boot process to check for the existence of an LFS image and run whichever module is required. Once the LFS module table has been registered by running [lua_examples/lfs/_init.lua](https://github.com/nodemcu/nodemcu-firmware/tree/dev/lua_examples/lfs/_init.lua) , running an LFS module is simple a matter of eg: `LFS.main()`.
[node.flashreload()](../modules/node/#nodeflashreload) need only be rerun if the LFS image is updated; after it has loaded the LFS image into flash memory the original file (in SPIFFS) is no longer used, and can be deleted.
Once LFS is known to work, then modules such as [lua_examples/lfs/dummy_strings.lua](https://github.com/nodemcu/nodemcu-firmware/tree/dev/lua_examples/lfs/dummy_strings.lua) can usefully be added, together of course with effective error checking.
This module provides a simple wrapper around long running functions to allow
these to execute within the SDK and its advised limit of 15 mSec per individual
task execution. It does this by exploiting the standard Lua coroutine
functionality as described in the [Lua RM §2.11](https://www.lua.org/manual/5.1/manual.html#2.11) and [PiL Chapter 9](https://www.lua.org/pil/9.html).
The NodeMCU Lua VM fully supports the standard coroutine functionality. Any
interactive or callback tasks are executed in the default thread, and the coroutine
itself runs in a second separate Lua stack. The coroutine can call any library
functions, but any subsequent callbacks will, of course, execute in the default
stack.
Interaction between the coroutine and the parent is through yield and resume
statements, and since the order of SDK tasks is indeterminate, the application
must take care to handle any ordering issues. This particular example uses
the `node.task.post()` API with the `taskYield()`function to resume itself,
so the running code can call `taskYield()` at regular points in the processing
to spilt the work into separate SDK tasks.
A similar approach could be based on timer or on a socket or pipe CB. If you
want to develop such a variant then start by reviewing the source and understanding
what it does.
### Require
```lua
localcohelper=require("cohelper")
-- or linked directly with the `exec()` method
require("cohelper").exec(func,<params>)
```
### Release
Not required. All resources are released on completion of the `exec()` method.
## `cohelper.exec()`
Execute a function which is wrapped by a coroutine handler.
#### Syntax
`require("cohelper").exec(func, <params>)`
#### Parameters
-`func`: Lua function to be executed as a coroutine.
-`<params>`: list of 0 or more parameters used to initialise func. the number and types must be matched to the funct declaration
#### Returns
Return result of first yield.
#### Notes
1. The coroutine function `func()` has 1+_n_ arguments The first is the supplied task yield function. Calling this yield function within `func()` will temporarily break execution and cause an SDK reschedule which migh allow other executinng tasks to be executed before is resumed. The remaining arguments are passed to the `func()` on first call.
2. The current implementation passes a single integer parameter across `resume()` / `yield()` interface. This acts to count the number of yields that occur. Depending on your appplication requirements, you might wish to amend this.
### Full Example
Here is a function which recursively walks the globals environment, the ROM table
and the Registry. Without coroutining, this walk terminate with a PANIC following
a watchdog timout. I don't want to sprinkle the code with `tmr.wdclr(`) that could
in turn cause the network stack to fail. Here is how to do it using coroutining:
```Lua
require "cohelper".exec(
function(taskYield, list)
local s, n, nCBs = {}, 0, 0
local function list_entry (name, v) -- upval: taskYield, nCBs
print(name, v)
n = n + 1
if n % 20 == 0 then nCBs = taskYield(nCBs) end
if type(v):sub(-5) ~= 'table' or s[v] or name == 'Reg.stdout' then return end
@@ -22,21 +22,25 @@ Function used to connect to Redis server.
...
@@ -22,21 +22,25 @@ Function used to connect to Redis server.
`redis.connect(host, [port])`
`redis.connect(host, [port])`
#### Parameters
#### Parameters
-`host`: Redis host name or address
-`host` Redis host name or address
-`port`: Redis database port. Default value is 6379.
-`port` Redis database port. Default value is 6379.
#### Returns
#### Returns
Object with rest of the functions.
Object with rest of the functions.
## subscribe()
!!! important
You need to start calling this `connect()` function to obtain a Redis object. All other functions are invoked on this object. Note the difference between `redis.connect()` (single dot) and `redis:subscribe()` (colon).
## redis:subscribe()
Subscribe to a Redis channel.
Subscribe to a Redis channel.
#### Syntax
#### Syntax
`redis:subscribe(channel, handler)`
`redis:subscribe(channel, handler)`
#### Parameters
#### Parameters
-`channel`: Channel name
-`channel` Channel name
-`handler`: Handler function that will be called on new message in subscribed channel
-`handler` Handler function that will be called on new message in subscribed channel
#### Returns
#### Returns
`nil`
`nil`
...
@@ -48,8 +52,8 @@ Publish a message to a Redis channel.
...
@@ -48,8 +52,8 @@ Publish a message to a Redis channel.
The C implementation is deprecated and will be removed soon; please transition
to Lua code.
## ds18b20.read()
Issues a temperature conversion of all connected sensors on the onewire bus and returns the measurment results after a conversion delay in a callback function.
The returned measurements can be filtered through the ROM addresses passed as a table or by the family type.
The callback function gets invoked for every specified sensor.
#### Syntax
`ds18b20.read(CALLBACK, ROM[, FAMILY_ADDRESS])`
#### Parameters
-`CALLBACK` callback function executed for each sensor
-`ROM` table which contains the addresses for the specified sensors, or left empty to perform a onewire bus search for all sensors
* e.g. `{"28:FF:FF:FF:FF:FF:FF:FF","28:FF:FF:FF:FF:FF:FF:FF"}`, `{}`
-`FAMILY_ADDRESS` optional to limit the search for devices to a specific family type
* e.g `0x28`
#### Returns
`nil`
#### Callback function parameters
-`INDEX` index of the sensor on the bus
-`ROM` sensors 64-bit lasered rom code
*`28:FF:FF:FF:FF:FF:FF:FF` LSB, 8-bit family code, 48-bit serial number, MSB 8-bit crc
-`RES` temperature resolution
-`TEMP` temperature
-`TEMP_DEC` temperature decimals for integer firmware
-`PAR` sensor parasitic flag
!!! note
If using float firmware then `temp` is a floating point number. On an integer firmware, the final value has to be concatenated from `temp` and `temp_dec`.
#### Example
```lua
localow_pin=3
ds18b20.setup(ow_pin)
-- read all sensors and print all measurement results
-- those wifi_* are the base parameters that are saved anyway
localp={}
p.wifi_ssid="ssid"
p.wifi_password="password"
-- your own parameters:
p.timeout_delay="xxx"
p.device_name="yyy"
returnp
```
After running [`enduser_setup.start()`](#enduser_setupstart), a wireless network named "SetupGadget_XXXXXX" will start (this prefix can be overridden in `user_config.h` by defining
### How to use the eus_params.lua file
`ENDUSER_SETUP_AP_SSID`). Connect to that SSID and then navigate to the root
of any website (e.g., `http://example.com/` will work, but do not use `.local` domains because it will fail on iOS). A web page similar to the picture above will load, allowing the
end user to provide their Wi-Fi information.
After an IP address has been successfully obtained, then this module will stop as if [`enduser_setup.stop()`](#enduser_setupstop) had been called. There is a 10-second delay before
Simply include the file by using the `dofile` function:
teardown to allow connected clients to obtain a last status message while the SoftAP is still active.
```lua
p=dofile('eus_params.lua')
-- now use the parameters in the Lua table
print("Wifi device_name: "..p.device_name)
```
Alternative HTML can be served by placing a file called `enduser_setup.html` on the filesystem. Everything needed by the web page must be included in this one file. This file will be kept
### HTTP endpoints:
in RAM, so keep it as small as possible. The file can be gzip'd ahead of time to reduce the size (i.e., using `gzip -n` or `zopfli`), and when served, the End User Setup module will add
the appropriate `Content-Encoding` header to the response.
*Note: If gzipped, the file can also be named `enduser_setup.html.gz` for semantic purposes. Gzip encoding is determined by the file's contents, not the filename.*
|Path|Method|Description|
|----|------|-----------|
|/|GET|Returns HTML for the web page. Will return the contents of `enduser_setup.html` if it exists on the filesystem, otherwise will return a page embedded into the firmware image.|
|/aplist|GET|Forces the ESP8266 to perform a site survey across all channels, reporting access points that it can find. Return payload is a JSON array: `[{"ssid":"foobar","rssi":-36,"chan":3}]`|
|/generate_204|GET|Returns a HTTP 204 status (expected by certain Android clients during Wi-Fi connectivity checks)|
|/status|GET|Returns plaintext status description, used by the web page|
|/status.json|GET|Returns a JSON payload containing the ESP8266's chip id in hexadecimal format and the status code: 0=Idle, 1=Connecting, 2=Wrong Password, 3=Network not Found, 4=Failed, 5=Success|
|/setwifi|POST|HTML form post for setting the WiFi credentials. Expects HTTP content type `application/x-www-form-urlencoded`. Supports sending and storing additinal configuration parameters (as input fields). Returns the same payload as `/status.json` instead of redirecting to `/`. See also: `/update`.|
|/update|GET|Data submission target. Example: `http://example.com/update?wifi_ssid=foobar&wifi_password=CorrectHorseBatteryStaple`. Will redirect to `/` when complete. Note that will NOT update the `eus_params.lua` file i.e. it does NOT support sending arbitrary parameters. See also: `/setwifi`. |
The following HTTP endpoints exist:
Module functions are described below.
|Endpoint|Description|
|--------|-----------|
|/|Returns HTML for the web page. Will return the contents of `enduser_setup.html` if it exists on the filesystem, otherwise will return a page embedded into the firmware image.|
|/aplist|Forces the ESP8266 to perform a site survey across all channels, reporting access points that it can find. Return payload is a JSON array: `[{"ssid":"foobar","rssi":-36,"chan":3}]`|
|/generate_204|Returns a HTTP 204 status (expected by certain Android clients during Wi-Fi connectivity checks)|
|/status|Returns plaintext status description, used by the web page|
|/status.json|Returns a JSON payload containing the ESP8266's chip id in hexadecimal format and the status code: 0=Idle, 1=Connecting, 2=Wrong Password, 3=Network not Found, 4=Failed, 5=Success|
|/setwifi|Endpoint intended for services to use for setting the wifi credentials. Identical to `/update` except returns the same payload as `/status.json` instead of redirecting to `/`.|
|/update|Form submission target. Example: `http://example.com/update?wifi_ssid=foobar&wifi_password=CorrectHorseBatteryStaple`. Must be a GET request. Will redirect to `/` when complete. |
## enduser_setup.manual()
## enduser_setup.manual()
Controls whether manual AP configuration is used.
Controls whether manual AP configuration is used.
By default the `enduser_setup` module automatically configures an open access point when starting, and stops it when the device has been successfully joined to a WiFi network. If manual mode has been enabled, neither of this is done. The device must be manually configured for `wifi.SOFTAP` mode prior to calling `enduser_setup.start()`. Additionally, the portal is not stopped after the device has successfully joined to a WiFi network.
By default the `enduser_setup` module automatically configures an open access
point when starting, and stops it when the device has been successfully joined
to a WiFi network. If manual mode has been enabled, neither of this is done.
The device must be manually configured for `wifi.SOFTAP` mode prior to calling
`enduser_setup.start()`. Additionally, the portal is not stopped after the
device has successfully joined to a WiFi network.
#### Syntax
#### Syntax
`enduser_setup.manual([on_off])`
`enduser_setup.manual([on_off])`
#### Parameters
#### Parameters
-`on_off` a boolean value indicating whether to use manual mode; if not given, the function only returns the current setting.
-`on_off` a boolean value indicating whether to use manual mode; if not
given, the function only returns the current setting.
#### Returns
#### Returns
The current setting, true if manual mode is enabled, false if it is not.
The current setting, true if manual mode is enabled, false if it is not.
I²C (I2C, IIC) is a serial 2-wire bus for communicating with various devices. Also known as SMBus or TWI, though SMBus have some additions to the I2C protocol.
ESP8266 chip does not have hardware I²C, so module uses software I²C driver.
It can be set up on any GPIO pins including GPIO16 (see below).
This module supports:
- Master mode
- Multiple buses (up to 10) with different speeds on each bus
- Standard(Slow, 100kHz), Fast(400kHz) and FastPlus(1MHz) modes or an arbitrary clock speed
- Clock stretching (slow slave device can tell the master to wait)
- Sharing SDA line over multiple I²C buses to save available pins
- GPIO16 pin can be used as SCL pin, but selected bus will be limited to not more than FAST speed.
HIGH-speed mode (3.5MHz clock) and 10-bit addressing scheme is not supported.
You have to call `i2c.setup` on a given I²C bus at least once before communicating to any device connected to that bus, otherwise you will get an error.
I²C bus designed to work in open-drain mode, so it needs pull-up resistors 1k - 10k on SDA and SCL lines. Though many peripheral modules have pull-up resistors onboard and will work without additional external resistors.
Hint for using many identical devices with same address:
Many devices allow to choose between 2 I²C addresses via pin or soldered 0 Ohm resistor.
If address change is not an option or you need to use more than 2 similar devices, you can use different I²C buses.
Initialize them once by calling `i2c.setup` with different bus numbers and pins, then refer to each device by bus id and device address.
SCL pins should be different, SDA can be shared on one pin.
Note that historically many NodeMCU drivers and modules assumed that only a single I²C bus with id 0 is available, so it is always safer to start with id 0 as first bus in your code.
If your device driver functions do not have I²C bus id as an input parameter and/or not built with Lua OOP principles then most probably device will be accessible through bus id 0 only and must be connected to its pins.
To enable new driver comment line `#define I2C_MASTER_OLD_VERSION` in `user_config.h`
To enable support for GPIO16 (D0) uncomment line `#define I2C_MASTER_GPIO16_ENABLED` in `user_config.h`
GPIO16 does not support open-drain mode and works in push-pull mode. That may lead to communication errors when slave device tries to stretch SCL clock but unable to hold SCL line low. If that happens, try setting lower I²C speed.
!!! caution
If your module reboots when trying to use GPIO16 pin, then it is wired to RESET pin to support deep sleep mode and you cannot use GPIO16 for I²C bus or other purposes.
## i2c.address()
## i2c.address()
Setup I²C address and read/write mode for the next transfer.
Setup I²C address and read/write mode for the next transfer.
On I²C bus every device is addressed by 7-bit number. Address for the particular device can be found in its datasheet.
#### Syntax
#### Syntax
`i2c.address(id, device_addr, direction)`
`i2c.address(id, device_addr, direction)`
#### Parameters
#### Parameters
-`id`always 0
-`id`bus number
-`device_addr` 7-bit device address, remember that [in I²C `device_addr` represents the upper 7 bits](http://www.nxp.com/documents/user_manual/UM10204.pdf#page=13) followed by a single `direction` bit
-`device_addr` 7-bit device address. Remember that [in I²C `device_addr` represents the upper 7 bits](http://www.nxp.com/documents/user_manual/UM10204.pdf#page=13) followed by a single `direction` bit. Sometimes device address is advertised as 8-bit value, then you should divide it by 2 to get 7-bit value.
-`direction``i2c.TRANSMITTER` for writing mode , `i2c. RECEIVER` for reading mode
-`direction``i2c.TRANSMITTER` for writing mode , `i2c. RECEIVER` for reading mode
#### Returns
#### Returns
...
@@ -27,7 +67,7 @@ Read data for variable number of bytes.
...
@@ -27,7 +67,7 @@ Read data for variable number of bytes.
`i2c.read(id, len)`
`i2c.read(id, len)`
#### Parameters
#### Parameters
-`id`always 0
-`id`bus number
-`len` number of data bytes
-`len` number of data bytes
#### Returns
#### Returns
...
@@ -39,11 +79,11 @@ id = 0
...
@@ -39,11 +79,11 @@ id = 0
sda=1
sda=1
scl=2
scl=2
-- initialize i2c, set pin1 as sda, set pin2 as scl
-- initialize i2c, set pin1 as sda, set pin2 as scl
i2c.setup(id,sda,scl,i2c.SLOW)
i2c.setup(id,sda,scl,i2c.FAST)
-- user defined function: read from reg_addr content of dev_addr
-- user defined function: read 1 byte of data from device
functionread_reg(dev_addr,reg_addr)
functionread_reg(id,dev_addr,reg_addr)
i2c.start(id)
i2c.start(id)
i2c.address(id,dev_addr,i2c.TRANSMITTER)
i2c.address(id,dev_addr,i2c.TRANSMITTER)
i2c.write(id,reg_addr)
i2c.write(id,reg_addr)
...
@@ -56,29 +96,51 @@ function read_reg(dev_addr, reg_addr)
...
@@ -56,29 +96,51 @@ function read_reg(dev_addr, reg_addr)
end
end
-- get content of register 0xAA of device 0x77
-- get content of register 0xAA of device 0x77
reg=read_reg(0x77,0xAA)
reg=read_reg(id,0x77,0xAA)
print(string.byte(reg))
print(string.byte(reg))
```
```
####See also
####See also
[i2c.write()](#i2cwrite)
[i2c.write()](#i2cwrite)
## i2c.setup()
## i2c.setup()
Initialize the I²C module.
Initialize the I²C bus with the selected bus number, pins and speed.
#### Syntax
#### Syntax
`i2c.setup(id, pinSDA, pinSCL, speed)`
`i2c.setup(id, pinSDA, pinSCL, speed)`
####Parameters
####Parameters
-`id`always 0
-`id`0~9, bus number
-`pinSDA` 1~12, IO index
-`pinSDA` 1~12, IO index
-`pinSCL` 1~12, IO index
-`pinSCL` 0~12, IO index
-`speed` only `i2c.SLOW` supported
-`speed``i2c.SLOW` (100kHz), `i2c.FAST` (400kHz), `i2c.FASTPLUS` (1MHz) or any clock frequency in range of 25000-1000000 Hz.
FASTPLUS mode results in 600kHz I2C clock speed at default 80MHz CPU frequency. To get 1MHz I2C clock speed change CPU frequency to 160MHz with function `node.setcpufreq(node.CPU160MHZ)`.
#### Returns
#### Returns
`speed` the selected speed
`speed` the selected speed, `0` if bus initialization error.
-`event` can be "connect", "message", "offline" or "overflow"
-`event` can be "connect", "suback", "unsuback", "puback", "message", "overflow", or "offline"
-`function(client[, topic[, message]])` callback function. The first parameter is the client. If event is "message", the 2nd and 3rd param are received topic and message (strings).
-`function(client[, topic[, message]])` callback function. The first parameter is the client. If event is "message", the 2nd and 3rd param are received topic and message (strings).
#### Returns
#### Returns
...
@@ -231,8 +231,13 @@ Publishes a message.
...
@@ -231,8 +231,13 @@ Publishes a message.
-`message` the message to publish, (buffer or string)
-`message` the message to publish, (buffer or string)
-`qos` QoS level
-`qos` QoS level
-`retain` retain flag
-`retain` retain flag
-`function(client)` optional callback fired when PUBACK received. NOTE: When calling publish() more than once, the last callback function defined will be called for ALL publish commands.
-`function(client)` optional callback fired when PUBACK received.
#### Notes
When calling publish() more than once, the last callback function defined will
be called for ALL publish commands. This callback argument also aliases with
the "puback" callback for `:on()`.
#### Returns
#### Returns
`true` on success, `false` otherwise
`true` on success, `false` otherwise
...
@@ -249,7 +254,13 @@ Subscribes to one or several topics.
...
@@ -249,7 +254,13 @@ Subscribes to one or several topics.
-`topic` a [topic string](http://www.hivemq.com/blog/mqtt-essentials-part-5-mqtt-topics-best-practices)
-`topic` a [topic string](http://www.hivemq.com/blog/mqtt-essentials-part-5-mqtt-topics-best-practices)
-`qos` QoS subscription level, default 0
-`qos` QoS subscription level, default 0
-`table` array of 'topic, qos' pairs to subscribe to
-`table` array of 'topic, qos' pairs to subscribe to
-`function(client)` optional callback fired when subscription(s) succeeded. NOTE: When calling subscribe() more than once, the last callback function defined will be called for ALL subscribe commands.
-`function(client)` optional callback fired when subscription(s) succeeded.
#### Notes
When calling subscribe() more than once, the last callback function defined
will be called for ALL subscribe commands. This callback argument also aliases
with the "suback" callback for `:on()`.
#### Returns
#### Returns
`true` on success, `false` otherwise
`true` on success, `false` otherwise
...
@@ -278,7 +289,13 @@ Unsubscribes from one or several topics.
...
@@ -278,7 +289,13 @@ Unsubscribes from one or several topics.
#### Parameters
#### Parameters
-`topic` a [topic string](http://www.hivemq.com/blog/mqtt-essentials-part-5-mqtt-topics-best-practices)
-`topic` a [topic string](http://www.hivemq.com/blog/mqtt-essentials-part-5-mqtt-topics-best-practices)
-`table` array of 'topic, anything' pairs to unsubscribe from
-`table` array of 'topic, anything' pairs to unsubscribe from
-`function(client)` optional callback fired when unsubscription(s) succeeded. NOTE: When calling unsubscribe() more than once, the last callback function defined will be called for ALL unsubscribe commands.
-`function(client)` optional callback fired when unsubscription(s) succeeded.
#### Notes
When calling subscribe() more than once, the last callback function defined
will be called for ALL subscribe commands. This callback argument also aliases