When it comes to embedded development, radios are something which is often highly complex and difficult to master. There is a whole ocean of requests and responses, definitions and setups, a two digit number of source files, just to get a byte transferred over the air, for starters. Over the years, a lot of radio protocols and names have emerged, each one excelling at some particular criteria.
Want fast transmission with big chunks of data? WiFi is probably the thing for you. Want to transmit fewer data and use as less energy as possible? BLE is probably the thing for you. But just imagine this - a radio that doesn't need a power source? Yes, I said it, go back and read it again, it doesn't need a power source. Not even a battery. It's called EnOcean, and it's pretty cool! In this article we will go over EnOcean radios, see how they work, and do a simple example with our EnOcean click board and EnOcean 2 click board!
EnOcean can be found in smart homes, automation systems, industrial systems etc. The EnOcean wireless modules use energy converters and low power electronics to form energy efficient, low power, battery-free wireless sensors, gateways, switches etc. So how exactly do they get this energy? EnOcean makes use of it's surroundings as much as possible, it generates it's electrical energy by converting electromagnetic, solar, and thermoelectric converters. That means that EnOcean can be charged by leaving it out in the sun, by using the temperature changes in the room where it is kept, or even by using physical motion.
Data rate, transmission frequency and range
EnOcean click: A data packet consists of 14 bytes, and is transmitted at a rate of 125 kbit/s. The transmission range is up 30 meters in buildings and 300 meters in free field. EnOcean transmits on one of the following frequencies: 868, 902 and 928MHz.
While EnOcean 2 click carries the TCM 515Z that enables the realization of line-powered actuators, controllers, and gateways communicating based on the 2.4 GHz IEEE 802.15.4 radio standard.
ESP3
Our EnOcean modules operate on the EnOcean Serial Protocol 3 (ESP3). This protocol specifies how the module communicates with it's host (MCU). We will take an overview over this protocol, as it will help us establish a connection between our EnOcean click and our host MCU.
Packet Structure
Packets are being transferred between the MCU and the EnOcean module using UART. Each packet consists of a header, data and optional data, the packet also contains a synchronization byte, a CRC byte for the header and a CRC byte for the data.
The header filed of the packet consists of the following fields: data length, optional data length and packet type. Data length field contains the number of bytes stored in the data field, optional data length is the same but for optional data, and the packet type field contains defines the type of the packet sent (or received), which we will discuss in a minute.
Description of the EnOcean data packe
Detailed description of the data packet
So how would this look in code? We would have 2 structures, one for the header, and the other for the packet, which would, of course, contain a header struct inside
typedef struct { uint16_t dataLength; uint8_t oppDataLength; PacketType packetType; } ESP3Header; typedef struct { uint8_t syncByte; ESP3Header header; uint8_t headerCRC; uint8_t* dataESP3; uint8_t* optData; uint8_t dataCRC; } ESP3Pack;
Now let's take a look at all the packet types available:
All available packet types
Logically, we would have the following enum:
typedef enum { RADIO_ERP1 = 0x01, // Radio telegram RESPONSE, // Response to any packet RADIO_SUB_TEL, //Radio subtelegram EVENT, //Event message COMMON_COMMAND, //Common command SMART_ACK_COMMAND, //Smart Ack command REMOTE_MAN_COMMAND, //Remote management command RADIO_MESSAGE = 0x09, // Radio message RADIO_ERP2 //ERP2 protocol radio telegram } PacketType; //0x08 and >0x0B reserved for enOcean
Here we will discuss the first two types of packets: RADIO_ERP1 - the radio telegram, and RESPONSE - the various responses available.
RADIO_ERP1
The ERP1 radio telegram (raw data) is embedded into the ESP3 packet. The actual user data (variable length) is a subset of the radio telegram. The packet is structured as follows:
Structure of the ERP1 packet
Here's one simple example of how the packet would look:
Simple example of the ERP1 packet
RESPONSE
Responses have the following packet structure:
Response packet structure
Here's the list of the available responses:
Available responses
Let's Get to Coding!
Okay, now that we have a basic understanding of the ESP3, we can make a simple example! We will use the EnOcean click with the PIC32MX795F512L. The library which we have provided has functions for making an ESP3 packet header, an ESP3 packet, and sending and receiving packets as well. In our example, though, we will not be sending, but strictly receiving packets. We will create a pointer to an ESP3 packet structure, and there we will store our received message. After receiving the message, we will parse it, and our MCU will react depending on the message.
#include "EnOcean.h" uint8_t* tempData; uint8_t* optTempData; ESP3Pack packFromClick; // Declare variables char temp1; char temp2; char cond; extern char tickTime; // Initialize timer void InitTimer2_3(){ T2CON = 0x8008; T3CON = 0x0; TMR2 = 0; TMR3 = 0; T3IE_bit = 1; T3IF_bit = 0; T3IP0_bit = 1; T3IP1_bit = 1; T3IP2_bit = 1; PR2 = 13568; PR3 = 12; } // Init timer interupt void Timer2_3Interrupt() iv IVT_TIMER_3 ilevel 7 ics ICS_SRS{ T3IF_bit = 0; tickTime++; } /********************************************************************************** * MAIN Function ***********************************************************************************/ void main(){ uint8_t ret = 1; uint8_t temp = 0; AD1PCFG = 0xFFFF; JTAGEN_bit = 0; // Disable JTAG TRISA = 0; TRISB = 0x00; TRISC = 0x00; TRISE = 0x00; TRISD = 0x00; TRISF = 0x00; LATC.B1 = 0; LATC.B2 = 0; LATC.B3 = 0; LATC = 0; LATA = 0; LATB = 0x00; LATE = 0x00; LATD = 0x00; LATF = 0x00; UART2_Init(57600); delay_ms(100); InitTimer2_3(); EnableInterrupts(); packFromClick.header.dataLength = 0; packFromClick.header.oppDataLength = 0; // Endless loop while(1){ if(U2STAbits.OERR){ U2STAbits.OERR = 0; UART2_Init(57600); } ret = recieveMessage(&packFromClick); // poll for a received message if(ret==0){ if(packFromClick.dataESP3[2]==0x00 && packFromClick.dataESP3[3]== 0x2B && packFromClick.dataESP3[4]==0x6A && packFromClick.dataESP3[5] == 0x64){ // Switch OFF command received if(packFromClick.dataESP3[1]== 0x30){ LATA = 0; // Set PORTA to zero LATB = 0x00; // Set PORTB to zero cond = 0; } // Switch ON command received else if(packFromClick.dataESP3[1]== 0x10){ LATA = 0xFF; // Set PORTA to 1 PORTB = 0x01; // Set first bit on port B cond = 1; } // Change state + command received else if((packFromClick.dataESP3[1]== 0x50) && (cond == 1)){ temp1 = PORTB; temp2 = temp1<<1; PORTB = temp2 + 0x01; } // Change state - command received else if((packFromClick.dataESP3[1]== 0x70) && (cond == 1)){ temp1 = PORTB; temp2 = temp1>>1; PORTB = temp2; } } } } }
There are 4 messages which we can receive from our EnOcean switch. Those can be used to switch ON or OFF, or to increase or decrease a certain feature. ON and OFF will control the state of the LEDs on our port A and B. And the increase and decrease command will control how many LEDs are lit at the port B.
The EnOcean Click library can be found on libstock.