NodeMCU Lua setup using a Mac

I recently bought a NodeMCU. This is a small ESP8266 based card with built in WiFi, MicroUSB, and a Lua interpreter that can be used for developing IoT (Internet of Things) devices.

I had trouble getting it working initially, so I wanted to share how I fixed this on a Mac.

Install Mac drivers

If you’re not using a Mac, you can skip this part.

You plug the NodeMCU into the Mac via USB. The Mac won’t support this by default, and you need to install a driver. The driver you need to install is the Silcon Labs CP210x USB to UART Bridge.

Once installed, plug in the NodeMCU and check that the device /dev/tty.SLAB_USBtoUART exists.

To connect to the NodeMCU, you’ll need some tools. To test, download CoolTerm. In Options, for Port select SLAB_USBtoUART, and for Baudrate select 115200.

If you are lucky you’ll get a prompt, if not you may need to build and install some new firmware.

If you do get a prompt type…

print "Hello";

… and Lua should echo “Hello” back to you.

Build and install the NodeMCU firmware

If you need to build new firmware, there is a very useful online site called NodeMCU-Build.com that I used to build the firmware with the right modules I wanted for my project.

Once you’ve build the firmware, you’ll need to install the Python esptool.py to flash the firmware to the NodeMCU.

git clone https://github.com/themadinventor/esptool.git
cd esptool
sudo python ./setup.py install

Check the flash size of your NodeMCU.

To flash the firmware hold down “FLASH” and press “RST” on the NodeMCU, then use the following command (remembering to disconnect CoolTerm first if connected)…

esptool.py --port /dev/tty.SLAB_USBtoUART write_flash -fm dio 0x00000 ~/Downloads/nodemcu-master-12-modules-2017-07-07-21-24-03-float.bin

As esptool.py runs, you should see something like this…

esptool.py v2.0.1
Connecting........_
Detecting chip type... ESP8266
Chip is ESP8266
Uploading stub...
Running stub...
Stub running...
Configuring flash size...
Auto-detected Flash size: 4MB
Flash params set to 0x0240
Compressed 754992 bytes to 505060...
Wrote 754992 bytes (505060 compressed) at 0x00000000 in 44.5 seconds (effective 135.6 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting...

Connect to it using CoolTerm, then press the “RST” button. You should see some messy characters, then something like following (depending on what you built into your firmware)…

NodeMCU custom build by frightanic.com
.branch: master
.commit: c8ac5cfb912ff206b03dd7c60ffbb2dafb83fe5e
.SSL: true
.modules: adc,bit,cron,crypto,encoder,file,gpio,http,i2c,net,node,ow,pcm,sjson,sntp,spi,struct,tmr,u8g,uart,websocket,wifi,tls
 build .built on: 2017-07-12 09:30
 powered by Lua 5.1.4 on SDK 2.1.0(116b762)
lua: cannot open init.lua
>

Upload Lua code to the NodeMCU

The best way to get Lua code onto the NodeMCU is to use the Python luatool.

git clone https://github.com/4refr0nt/luatool
cd luatool

To test we’ll upload a simple Lua script that will blink the NodeMCU’s onboard LED, save this as “blink.lua”.

LED_PIN = 0

gpio.mode(LED_PIN, gpio.OUTPUT)
value = true

tmr.alarm(0, 500, 1, function ()
    gpio.write(LED_PIN, value and gpio.HIGH or gpio.LOW)
    value = not value
end)

Upload it to the NodeMCU using the following command (making sure Coolterm is disconnected first)…

python luatool/luatool.py --port /dev/tty.SLAB_USBtoUART --src blink.lua --dest init.lua --dofile

You should see the following…

->file.open("init.lua", "w") -> ok
->file.close() -> ok
->file.remove("init.lua") -> ok
->file.open("init.lua", "w+") -> ok
->file.writeline([==[LED_PIN = 0]==]) -> ok
->file.writeline([==[]==]) -> ok
->file.writeline([==[gpio.mode(LED_PIN, gpio.OUTPUT)]==]) -> ok
->file.writeline([==[value = true]==]) -> ok
->file.writeline([==[]==]) -> ok
->file.writeline([==[tmr.alarm(0, 500, 1, function ()]==]) -> ok
->file.writeline([==[gpio.write(LED_PIN, value and gpio.HIGH or gpio.LOW)]==]) -> ok
->file.writeline([==[value = not value]==]) -> ok
->file.writeline([==[end)]==]) -> ok
->file.flush() -> ok
->file.close() -> ok
->dofile("init.lua") -> send without check
--->>> All done <<<--

The onboard LED on the NodeMCU should now be blinking.

The NodeMCU executes the init.lua script by default, so when we upload we tell luatool to upload our blink.lua script as init.lua.

Using a motion sensor on a Raspberry Pi with PHP

Adding a motion sensor to a Raspberry Pi is easy. In this article I’ll show you how to use it with PHP.

The HC-SR501 is a pyroelectric infrared PIR motion sensor module, that connects to the Raspberry Pi using just 3 wires.

Connect GND to GND on the Pi, VCC to +5V on the Pi, and OUT to GPIO 17 on the Pi. That’s all that’s needed.

Added a HC-SR501 motion detector to a Raspberry Pi

To use the sensor with PHP we use the PHPi library. This library supports event driven bindings for the Raspberry Pi GPIO. We install this using Composer.

composer require calcinai/phpi

To use the PHPi library we need to bring it in using the autoloader, and add some namespace shortcuts.

require 'vendor/autoload.php';

use Calcinai\PHPi\Pin;
use Calcinai\PHPi\Pin\PinFunction;

We then create a board

$board = \Calcinai\PHPi\Factory::create();

We now need to declare that we’re using GPIO pin 17 for input.

$pin = $board->getPin(17)
             ->setFunction(PinFunction::INPUT)
             ->setPull(Pin::PULL_UP);

As this is event driven programming, we need to listen to the pin to see when it changes. When the pin goes high, we know motion has been detected and we can do something. In this example, we’ll just write a message to the screen.

$pin->on('level.high', function() {
        echo "Motion detected\n";
});

Finally we start the start the loop running, so the script is listening and reacting to events.

$board->getLoop()->run();

Putting it all together

Here’s the final working PHP to detect motion using the HC-SR501

<?php

require 'vendor/autoload.php';

use Calcinai\PHPi\Pin;
use Calcinai\PHPi\Pin\PinFunction;

$board = \Calcinai\PHPi\Factory::create();

$pin = $board->getPin(17) //BCM pin number
             ->setFunction(PinFunction::INPUT)
             ->setPull(Pin::PULL_UP);

$pin->on('level.high', function() {
        echo "Motion detected\n";
});

$board->getLoop()->run();

Reading a temperature sensor using PHP on a Raspberry Pi

It’s easy to add a temperature sensor to a Raspberry Pi. In this example I’ll explain how to set it up and access the data using PHP.

The DS18b20 is a great digital temperature sensor. It only needs three wires and a resistor to get it working on the Raspberry Pi.

The red wire is +3.3v, the black is ground, and yellow is data.

The resistor is connected between red and yellow to pull up the voltage on the data line.

Red is connected to pin 1 on the GPIO, black to pin 6, and yellow to pin 7.

Connecting a temperature sensor to a Raspberry Pi

Reading the temperature

Now the circuit is ready, we can access the data. We need to enable the relevant modules on the Raspberry Pi to do this.

modprobe w1-gpio
modprobe w1-therm

If we now look in the /sys/bus/w1/devices/ directory, we should see a directory starting with 28. This is where we can find the temperature data. Inside this directory is a file called w1_slave. This is the file we read get the data. When we read it, it actually asks the sensor for the data and return it. This means there is a slight delay before the data returns.

pi@Nowscreen:~ $ cat /sys/bus/w1/devices/28-031683a865ff/w1_slave
95 01 4b 46 7f ff 0c 10 65 : crc=65 YES
95 01 4b 46 7f ff 0c 10 65 t=25312

The temperature is the value t=25312. We divide this by 1000 to get the temperature of 25.312 degrees celcius.

Reading the temperature with PHP

The first thing we need to do is to find the directory where the w1_slave file is. We can use globbing to help here.

$base_dir = '/sys/bus/w1/devices/';
$device_folder = glob($base_dir . '28*')[0];
$device_file = $device_folder . '/w1_slave';

Now we need to read in the data. We can use the file method as this returns each line of the file in an array.

$data = file($device_file, FILE_IGNORE_NEW_LINES);

Now we extract the temperature. We check the first line is correct by checking for the value “YES” at the end of the line. If this is present we get the value for “t=” at the end of the second line. Finally we divide the value by 1000, and return it.

$temperature = null;
if (preg_match('/YES$/', $data[0])) {
    if (preg_match('/t=(\d+)$/', $data[1], $matches, PREG_OFFSET_CAPTURE)) {
        $temperature = $matches[1][0] / 1000;
    }
}

Now we can display the temperature.

if ($temperature) {
    echo "Temperature is ${temperature}C\n";
} else {
    echo "Unable to get temperature\n";
}

Final PHP temperature sensor code

Here’s the finished code. I’ve also included two system calls to modprobe to ensure the necessary modules are loaded before reading.

<?php

exec('modprobe w1-gpio');
exec('modprobe w1-therm');

$base_dir = '/sys/bus/w1/devices/';
$device_folder = glob($base_dir . '28*')[0];
$device_file = $device_folder . '/w1_slave';

$data = file($device_file, FILE_IGNORE_NEW_LINES);

$temperature = null;
if (preg_match('/YES$/', $data[0])) {
    if (preg_match('/t=(\d+)$/', $data[1], $matches, PREG_OFFSET_CAPTURE)) {
        $temperature = $matches[1][0] / 1000;
    }
}

if ($temperature) {
    echo "Temperature is ${temperature}C\n";
} else {
    echo "Unable to get temperature\n";
}

Controlling a LED on a Raspberry Pi with PHP

I wanted to make a LED light up using PHP on a Raspberry Pi. Most of the examples I’ve seen are for Python, so I wanted to see if was possible or not.

It is actually pretty easy to do, so I thought I’d share my work.

The first thing to do is to wire up the LED to the Raspberry Pi. I used a breadboard so there is no soldering required.

Connect the LED to GPIO pin 18, along with a 330ohm resistor, to GND. We need the resistor to limit the current through the LED otherwise it could burn out.

That’s the LED attached to Raspberry Pi, now we need to control it with PHP code.

PHP LED Control Code

Before we can write any PHP, we need to enable the gpio module on the Raspberry Pi.

sudo modprobe w1-gpio

We need a third party PHP library to be able to talk to the GPIO pins. I’m using php-gpio.

We need to install this with Composer before we can use it.

get http://getcomposer.org/composer.phar
php composer.phar require ronanguilloux/php-gpio

We can now start our PHP code by using the autoloader to bring in the GPIO library.

require 'vendor/autoload.php';

use PhpGpio\Gpio;
$gpio = new GPIO();

Now to control the LED we need to make sure GPIO pin 18 is set to “out”.

$gpio->setup(18, 'out');

To turn the LED on we write the value “1” to pin 18.

$gpio->output(18, 1);

To turn the LED off we write the value “0” to pin 18.

$gpio->output(18, 0);

Finally, we need to make sure we clean up after ourselves.

$gpio->unexportAll();

The Final Code

Bringing this all together, we can write a simple PHP script to turn the LED on, wait 1 second, and turn it off again.

<?php

require 'vendor/autoload.php';

use PhpGpio\Gpio;
$gpio = new GPIO();
$gpio->setup(18, 'out');

echo "LED on\n";
$gpio->output(18, 1);

sleep(1);

echo "LED off\n";
$gpio->output(18, 0);

$gpio->unexportAll();

The final code needs to be run as root to be able to access gpio.