Category Archives: HowTo’s

#ESP8266 #VSCP Development Intro – part 1

Serial port

Connect the USB cable to the board.  You will get a new CDC serial port. You can check which one you get with

ls /dev/tty*

Normally you get /dev/ttyUSB0 or /dev/ttyUSB1 or the like. To make them usable for you you should add yourself to the dialout group

addgroup user dialout

where “user” is your username. You can also do this manually in the /etc/group file or

chmod a+rw /dev/ttyUSB0

if you like brute force.

Loading code to the ESP8266

The ESP8266 CPU can be booted in three different ways:

  • Flash Mode: default booting mode. Firmware is read and executed from the flash memory. Pins need to be set to: GPIO15=0, GPIO0=0, GPIO2=1
  • UART Mode: used to program our board (through a Serial-to-Usb adapter). Pins need to be set to:  GPIO15=0, GPIO0=1, GPIO2=1
  • SDIO Mode: loads firmware from an SDIO card? Pins need to be set to:  GPIO15=1, GPIO0=0/1, GPIO2=0/1

The boot process is described here.

Switching from a mode to another requires to reset the module while the pin states listed is set.

With the nodemcu board and esptool flash uploader all this is handle automatically but if you have another board you must handle this yourself.

esp-open-sdk

You find it here.

Fetch it

sudo git clone https://github.com/pfalcon/esp-open-sdk.git

cd esp-open-sdk

Install it

apt-get install make unrar autoconf automake libtool libtool-bin gcc g++ gperf flex bison texinfo gawk ncurses-dev libexpat-dev python sed

git clone --recursive https://github.com/pfalcon/esp-open-sdk

cd esp-open-sdk/

make
Error when building?  See this post
This builds the standalone version of the SDK (Non FreeRTOS)
You should add the bin directory to he path
echo 'PATH=$PATH:~/development/esp8266/esp-open-sdk/xtensa-lx106-elf/bin' >> ~/.profile

echo 'PATH=$PATH:~/development/esp8266/esp-open-sdk/esptool' >> ~/.profile

PATH=$PATH:~/development/esp8266/esp-open-sdk/xtensa-lx106-elf/bin
PATH=$PATH:~/development/esp8266/esp-open-sdk/esptool

I have installed the toolchain in

 ~/development/esp8266/ 

so change paths above for your installation folders.

Update it (when updates are available)

make clean
git pull
git submodule update

Firmware upload tool

You need the esptool.py to upliad firmware to the module, you find it here
Install with
pip install esptool

First code (blinky)

You find it here

cd ~/development/esp8266/esp-open-sdk/examples/blinky

Type

make

to build it. Remember that the paths above must have been set. You may get some warnings. No problem.

For your information. If you build from source code should be loaded like this:

  • bin/0x00000.bin to 0x00000
  • bin/0x10000.bin to 0x10000

That is just what we do here. Upload to your module with

esptool.py --port /dev/ttyUSB1 write_flash 0x00000 blinky-0x00000.bin 0x10000 blinky-0x10000.bin

No need to press any buttons during flashing. It is handled automatically by the USB DTR circuitry.

Now we are ready to do some real work for our VSCP system with the ESP8266.  If you rather prefer Arduino this howto may be the one you should go for instead of this one. Life is much simpler in the Arduino world. But the degrees of freedom is better if you do it all by yourself. The penalty for freedom is more problems of course. As always.

Another intro is here http://www.electrodragon.com/w/ESP8266_Open_SDK
esp8266 wiki is here.

Part 2 will follow.

Howto: Minimum VSCP wifi Level II node (VSCP PID detector)

In this  howto we will build a simple VSCP level II node that with the help of a PIR motion sensor detects motion and sens this as a VSCP event wireless to a VSCP daemon.

We use the famous ESP8266  for this  and work in the even more famous Arduino environment.  The ESP8266 comes in many flavors but a convenient form factor is the NodeMCU board.  You can buy it on Aliexpress or Ebay at a low-cost (USD 2.2).

There is also a baseboard available for the NodeMCU and I use it as it is convenient when working with a new design. It to is available on Aliexpress and Ebay at a low-cost (USD 1.54).

The last item you need is the PIR sensor, they to are available at low-cost. I bought mine from Ebay (USD 0.99).

If you haven’t set up your Arduino IDE for work with the ESP8266 you need to do that now.  Here is an excellent tutorial on how to do this. Make the blink example work before you move on.

I find the Arduino IDE a bit crude to work with so I use Visual Studio Code instead.  An excellent programming editor that works on all the major operation systems. I tend to use it more and more. But there are other options to such as Atom. Anyway instructions on how to get it working for Arduino development is here.  Make sure to set the “output” tag to a valid location in the .vscode/arduino.json file otherwise upload will be VERY slow.

You also need a VSCP daemon/server running for this example. All info about it is here.

To connect the sensor to the NodeMCU we ned to know about he port mapping for the module which is a bit different from for other Arduino devices. It looks like this

static const uint8_t D0   = 16;
static const uint8_t D1   = 5;
static const uint8_t D2   = 4;
static const uint8_t D3   = 0;
static const uint8_t D4   = 2;
static const uint8_t D5   = 14;
static const uint8_t D6   = 12;
static const uint8_t D7   = 13;
static const uint8_t D8   = 15;
static const uint8_t D9   = 3;
static const uint8_t D10  = 1;

D0 has a blue LED connected to it so it is an obvious candidate for status. D1 can be used to connect to the PIR

The PIR device I have outputs a 3V signal even when powered with +5V so it is OK to connect directly to D1. So the three pins on the PIR

1     +5V
2     Output to D1 (High on detect)
3     GND

The LED on D0 light up when a LOW is written to it. This is opposite to the PIR output. We take care of this in software.

We implement a dump VSCP device here. This is a device that does not handle any of the register reads that “normal” VSCP requires and which don’t have a MDF file either. A dumb device has been 14 set in the header.

We send two events. The heartbeat event (CLASS1.INFORMATION, Type=9) every minute. This event is recommended for all nodes as it is used for node discovery and detection. The other event we send is the detect event (CLASS1.INFORMATION, Type=49 detect) when an object is detected.

The test setup looks like this

and you can find the complete code is here

The heartbeat coming into the VSCP daemon (using VSCP works)

and the detect event

With the event in the VSCP daemon it is easy to add a DM row that for instance light up the lamps in a room. You can also use the rest or the websocket interface to do give visual feedback.

We will follow-up this howto with a post where we use the Expressif SDK instead of the Arduino and use a plain ESP8266 board. But also a ost where we implement a full Level II node that have registers and a MDF and show the advantage we get with a node like that over a dumb one.

An alternative wifi lib is documented here.

 

#VSCP update process #howto

In previous versions of VSCP whenever you did an install all configuration files were replaced with the latest version. This is not true anymore.  Now the new version is instead written as a copy with the date of the install appended to it.  So if you after a “make install” or a “dpkg -i vscpd” want the latest configs you have to copy the backup to the actual config file and restart the VSCP server.

Files that is handled in this way is

/etc/vscp/vscpd.conf
/srv/vscp/dm.xml
/srv/vscp/simtempdata.txt
/srv/vscp/variables.xml

Also if you are on unstable code you should remove the databases before you start the updated server . Use

rm /srv/vscp/*.sqlite3

for this.

Also note that the web sample code is not installed in the install/update process no more. The process to get this subsystem installed with be described later.

#VSCP HOWTO: DM Using timers

Timers. One can wonder what they do in the decision matrix? They even have their own events defined in the CLASS2.VSCP class.

First let us define what a VSCP timer is.

A VSCP timer is a free running 32-bit timer with millisecond resolution.  That is they can hold  0xffffffff = 4294967295 milliseconds which mens they will roll over in about 50 days.

There are actions defined to

There is the following  internal events defined related to timers

To create and start a timer

<row enable="true" groupid="timers" >

  <comment>
    Create timer
  </comment>

  <mask priority="0"
        class="0xFFFF"
        type="0xFFFF"
 GUID="00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00" />

  <filter priority="0"
          class="65535"
          type="23"
 GUID="00:01:02:03:04:05:06:07:08:09:0A:0B:0C:0D:0E:0F" />

  <action>0x60</action>
  <param>
    1;10;timer1flag;true
  </param>

</row>

Here a timer with id = 1 is created. The timer has an initial time set to 10 seconds. When this timer elapses it will set the variable //timer1flag// to true. The last argument is the reload flag. Here it is set to true so when the time has elapsed the initial value will be loaded again and the timer will start again.

In the example above we could have added “;4” at the end of the parameter which would have the effect that the reload would stop after four runs. Default is thus forever.

When the timer is started a CLASS2.VSCPD, Type = 25 (0x0019) Timer started event is generated. When the ten seconds has gone and the timer elapses the  CLASS2.VSCPD, Type = 29 (0x001D) Timer Elapsed event is generated.

We can use either one of these two generated events to do any action periodically like this.

<row enable="true" groupid="timers" >

  <comment> 
    Handle timer elapsed
  </comment>

  <mask priority="0"
        class="0xFFFF"
        type="0xFFFF"
 GUID="00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00" />

  <filter priority="0"
          class="65535"
          type="29"
 GUID="00:01:02:03:04:05:06:07:08:09:0A:0B:0C:0D:0E:0F" />

  <action>0x70</action>
  <param>
    /srv/vscp/timefile;1;%isoboth: Timer with  id=%event.data.int32[0] elapsed %lf
  </param>

</row>


<row enable="true" groupid="timers" > 

   <comment> Handle timer elapsed </comment> 
   <mask priority="0" 
         class="0xFFFF" 
         type="0xFFFF" GUID="00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00" /> 
    <filter priority="0" 
            class="65535" 
            type="25" GUID="00:01:02:03:04:05:06:07:08:09:0A:0B:0C:0D:0E:0F" /> 

    <action>0x70</action> 
    <param> 
      /srv/vscp/timefile;1;%isoboth: Timer with id=%event.data.int32[0] elapsed counter=%event.data.uint32[0]ms %lf </param> </row>

Here some info is just written to a file when the timer is started and when it elapses.   But if you want to send an event periodically instead or do other actions this is the way to do it.

You don’t have to give a variable nor a reload flag when you start a timer. If no variable is given (use ;;) it is just ignored. The reload value will be set to false as default  value, that is the timer will run only once. As the last parameter you can set the number of times the timer should reload before it should stop.  The full documentation is here and here.

One useful use of timers is to handle resend of events. The working is like this

Send the event you expect a reply event from another node.

  1. Create/start a timer that have  period equal to resend intervals for the event you want to send. The timer should  have true for autoloading and the number of autoloads set to the number of resend that are allowed.  You can trigger the creation of the timer  by make a DM entry that triggering on one of the reserved events for example,  CLASS1.LOCAL  or CLASS1.LABORATORY so that when you send this local event  the actual event will be sent (see next point)
  2. In the timer started event send  the event you want to send.
  3. When/If the expected reply  is received pause the timer.
  4. Now if the timer the timer stopped event is detected the reply wait timeout has expired so do timeout handling there by sending another local event or CLASS1.ERROR, Type = 32 Time out.

Can be used for much more of course. Just useful and simple.

#VSCP HOWTO: DM write/append to file

The Level I logger and the Level II logger are great tools for logging events in a VSCP based system.  Useful also for debugging etc. Another method is to use the execute external program action and execute a script and write to a file there. We have seen this method being used in other howtos.  Also while running a JavaScript or a Lua script files can be written.

But…

file writing is also available as an action.  It is documented here. This action allows writing or appending a string with output to a named file that is created if it does not exist. With the VSCP escapes a lot of dynamic information can go into this file.

Suppose that we want to  log events of a certain type to a file, here CLASS1.DATA, Type=2 A/D values form a specific device. We then write a decision matrix (DM) row

<row enable="true" groupid="" >

<comment>
 Collect A/D values from node X
</comment>

<mask priority="0"
 class="0xFFFF"
 type="0xFFFF"
 GUID="FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF" />

<filter priority="0"
 class="15"
 type="2"
 GUID="00:01:02:03:04:05:06:07:08:09:0A:0B:0C:0D:0E:0F" />

<action>0x70</action>
 <param>
 /tmp/addata;1;%isoboth: %measurement.string %lf 
 </param>

</row>

will generate output content like this

With the other VSCP escapes and literals you have many options to generate meaningful output.

 

#VSCP HOWTO: DM Send events

In a previous howto we looked at how to link server interfaces. Sometimes it is not necessary to establish a full link but just send an event to the rest of the system.  A typical example on this can be when an event comes in that signals a special state and you what the system to go perform other steps. Here you can send out the events needed to perform those steps.

There are currently three actions defined for this in the VSCP server

Send event

VSCP_DAEMON_ACTION_CODE_SEND_EVENT    0x40/64

This actions sends out a specified event and optionally set a boolean variable to true if the send was successful.  The full documentation is here.

If for example you want to send the event CLASS1.INFORMATION, Type=3, ON every second you can use

<row enable="true" groupid="Send event">

<comment>
 Periodic event
 Send CLASS1:INFORMATION, Type=3 ON event every second
 </comment>

<mask priority="0"
 class="0xFFFF"
 type="0xFFFF"
 GUID=" 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00" />

<filter priority="0"
 class="65535"
 type="5"
 GUID=" 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00" />

<action>0x40</action>
 <param>
 0,20,3,0,,,0:1:2:3:4:5:6:7:8:9:10:11:12:13:14:15,0,1,35
 </param>

</row>

Send event conditional

VSCP_DAEMON_ACTION_CODE_SEND_EVENT_CONDITIONAL    0x41/65

This action works much as the previous action. The difference is that it just send the event if a named VSCP remote variable is true.  The full documentation is here.

If you like in the example above want to send the event CLASS1.INFORMATION, Type=3, ON every second you can use

<row enable="true" groupid="Send event conditional" >

<comment>
 Create variable that hold flag for sent event
 when the server is started ( CLASS2.VSCPD, Type=23 ).
 </comment>

<mask priority="0"
 class="0xFFFF"
 type="0xFFFF"
 GUID=" 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00" />

<filter priority="0"
 class="65535"
 type="23"
 GUID=" 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00" />

<action>0x50</action>
 <param>
 bsent;bool;false;0;0x777;false
 </param>

</row>
 
 <row enable="true" groupid="Send event conditional" >

<comment>
 Create variable that hold flag send conditional event
 when the server is started ( CLASS2.VSCPD, Type=23 ).
 </comment>

<mask priority="0"
 class="0xFFFF"
 type="0xFFFF"
 GUID=" 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00" />

<filter priority="0"
 class="65535"
 type="23"
 GUID=" 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00" />

<action>0x50</action>
 <param>
 bevent;bool;false;0;0x777;false
 </param>

</row>
<row enable="true" groupid="Send event conditional">

<comment>
Send event conditional
Send CLASS1:INFORMATION, Type=3 ON event
</comment>

<mask priority="0"
class="0xFFFF"
type="0xFFFF"
GUID=" 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00" />

<filter priority="0"
class="65535"
type="5"
GUID="00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00" />

<action>0x41</action>
<param>
bevent;0,20,3,0,,,0:1:2:3:4:5:6:7:8:9:10:11:12:13:14:15,0,1,35;bsent
</param>

</row>

The difference from the previous example is the introduction of the bEvent remote variable. This variable is initialized to false so before it is set to true no events will be sent.  We can look at the variable sin the admin web interface

Setting it to true

make the action trigger and the event is sent once a second while the bEvent variable is set to true.

 

 

Send event(s) from file

The last send event action send one or more events from a file instead of having them specified in the action parameter. This makes it possible to send several events from one trigger.  A typical scenario could be to trigger on button press and set a scene by presetting lamps and other things which will be set by the sent out list of events,

This action is fully specified here.  The file for the events to send out is XML based.  Apart from that it should be easy to set up from the documentation.

The events defined here in a file called sendevents simulate setting a scenario.

<events>

<event>
 <!-- 
 CLASS1.CONTROL, Type=5 TurnOn
 Turn on lamps in zone=1, subzon=0
 -->
 <head>0</head>
 <class>30</class>
 <type>5</type>
 <guid>00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00</guid> 
 <data>0,1,0</data>
 </event>

<event>
 <!-- 
 CLASS1.CONTROL, Type=5 TurnOn
 Turn on lamps in zone=1, subzon=0
 -->
 <head>0</head>
 <class>30</class>
 <type>5</type>
 <guid>00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00</guid> 
 <data>0,1,2</data>
 </event>

<event>
 <!-- 
 CLASS1.CONTROL, Type=5 TurnOn
 Turn on lamps in zone=1, subzon=22
 -->
 <head>0</head>
 <class>30</class>
 <type>5</type>
 <guid>00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00</guid> 
 <data>0,1,22</data>
 </event>

<event>
 <!-- 
 CLASS1.CONTROL, Type=5 TurnOn
 Turn on lamps in zone=1, subzon=240
 -->
 <head>0</head>
 <class>30</class>
 <type>5</type>
 <guid>00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00</guid> 
 <data>0,1,240</data>
 </event>

<event>
 <!-- 
 CLASS1.CONTROL, Type=6 TurnOff
 Turn off head light lamps in zone=1, subzon=1
 -->
 <head>0</head>
 <class>30</class>
 <type>6</type>
 <guid>00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00</guid> 
 <data>0,1,1</data>
 </event>

<event>
 <!-- 
 CLASS1.CONTROL, Type=20 Dim lamp(s)
 Dim lamps in zone=1, subzon=0 at 30%
 -->
 <head>0</head>
 <class>30</class>
 <type>20</type>
 <guid>00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00</guid> 
 <data>30,1,0</data>
 </event> 
 
</events>

A DM that sets this scenario every minute looks like this

<?xml version = "1.0" encoding = "UTF-8" ?>

<dm>

<row enable="true" groupid="Send events from file" >

<comment>
 Send events in list sendevents 
 when the server is started ( CLASS2.VSCPD, Type=23 ).
 </comment>

<mask priority="0"
 class="0xFFFF"
 type="0xFFFF"
 GUID="00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00" />

<filter priority="0"
 class="65535"
 type="6"
 GUID="00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00" />

<action>0x42</action>
 <param>
 /srv/vscp/sendevents
 </param>

</row>
 
 
</dm>

And running it we see in VSCP works that the events get sent

 

You can find sample files for tests here.