Zigbee2MQTT on RPI with CC2530/CC2591

So, if you’ve flashed a CC2530/CC2591 from my previous post, you now probably want to get it talking to something. Here’s how you can do that.


I will assume you are wanting to do the following;

  • Use a Raspberry Pi 2/3 running Raspbian to act at the bridge between the CC2530/CC2591 and MQTT.
  • You’re using Raspbian Stretch.
  • You want to use Zigbee2MQTT to get this thing talking to something like HomeAssistant.
  • You want to use the RPI’s built-in UART and directly wire the module to the RPI.
  • You don’t care about Bluetooth on the RPI.
  • You already have Docker installed on the RPI.
  • You already have Docker-Compose installed on the RPI.
  • You already have your CC2530/CC2591 flashed with KoenKK’s Z-Stack firmware, and it’s a recent version.
  • You have a mqtt server somewhere already.

Phew. Now with all that in line, let’s get moving.

Hardware Setup

CC2530/CC2591 Pinout Diagram
RPI2/3 GPIO Pinout

Using the two charts above, you will need to make the following connections;

VCC (Supply)VCC3V3
GND (Ground)GNDG
RXD (Receive Data)P0_2RPI Pin 8 (TXD)
TXD (Transmit Data)P0_3RPI Pin 10 (RXD)

This is the minimum set of pins required. Note that RXD on the CC2591 gets connected to TXD on the RPI. This is normal.

Do not connect the CC2530 to the 5V lines on the RPI. Doing so will likely destroy the CC2530.

Configure UART on the RPI

What we’ll be doing is using the UART on the RPI. There are a number of ways to do this, but we’ll use the method which disables Bluetooth and puts the UART on the high-performance device /dev/ttyAMA0.

Edit your /boot/config.txt and add the following;


Then edit /boot/cmdline.txt and remove the following bit from the only line;


Reboot your Pi, and you should now have the UART pins listed above manifest on /dev/ttyAMA0. Don’t try and use minicom or similar to connect to it, you won’t see much useful.

Set up a HomeAssistant Docker-Compose File

We’re going to use Docker Compose to run zigbee2mqtt in a container. Make a directory somewhere for it, and a data directory, like so;

mkdir -p /srv/zigbee2mqtt/data

Then edit /srv/zigbee2mqtt/docker-compose.yml, and fill it in like this;

version: '2'
image: koenkk/zigbee2mqtt:arm32v6
restart: always
- /srv/zigbee2mqtt/data:/app/data
- /dev/ttyAMA0:/dev/ttyAMA0

Now, this will spin up a zigbee2mqtt service when you start it, which will always restart when stopped, using /dev/ttyAMA0 as we defined earlier. Lastly, create a /srv/zigbee2mqtt/data/configuration.yaml and fill it in like this;

homeassistant: true
permit_join: true
base_topic: zigbee2mqtt
server: 'mqtt://YOURMQTTSERVERHERE:1883'
include_device_information: true
port: /dev/ttyAMA0
log_level: info
baudrate: 115200
rtscts: false

I strongly suggest you change the network key, and disable permit_join when you have all your devices up. There’s various other things to do here too, but this should get you started.

Once that’s done, a simple;

docker-compose up

Should bring up your container. Press Ctrl-\ to break out without terminating it.

Flashing Z-Stack on a CC2530+CC2591 using a Wemos D1 mini

I’m messing about with Zigbee for a comms protocol to various temperature sensors, and this requires a Zigbee Coordinator. There’s a few ways of doing this, but ultimately I settled on a zigbee2mqtt bridge and a cheapie AliExpress CC2530+CC2591 module.

This module incorporates an RF amplifier, but does not have the normal debug header that the CC2530 Zigbee transceivers have and also lacks the USB-TTL adapter chip. Not a problem if you’re using a RPi as the bridge, which is what I plan on doing.

However first, you need to get Z-Stack firmware on it, so you can use it as a coordinator. This proves to be… non-trivial. Especially if you want to use a Wemos D1 Mini as the flashing device (these Wemos things are really good, incidentally).

First Steps – Getting CClib-Proxy onto the Wemos

Assuming you have a Wemos D1 mini, your first steps are to install the Arduino IDE (available from the Windows Store). Once that’s in, in Preferences, add the following URL to the Additional Boards Manager URL field;


From there, you should now be able to go to the Boards Manager, and install the esp8266 package. Once that is installed, configure your board as a “LOLIN(WEMOS) D1 R2 & Mini” and select the correct COM port.

Now it’s as simple as downloading CCLib-Proxy from this link. Open up CCLib_Proxy.ino, then change the following lines for the pinout;

 int CC_RST   = 5;
int CC_DC = 4;
int CC_DD_I = 14;
int CC_DD_O = 12;

These mappings are required. Upload to your device. You now have CClib-Proxy onto the Wemos and ready to go.

Wiring up the Wemos to the CC2530+CC2591 Module

You will need to map various pins on the Wemos to pins on the module, using the following chart;

DC (Debug Clock)P2_2D2 (GPIO4)
DD (Debug Data)P2_1D5 (GPIO14)
D6 (GPIO12)
RST (Reset)RSTD1 (GPIO5)
VCC (Supply)VCC3V3
GND (Ground)GNDG
RXD (Receive Data)P0_2RPI Pin 8 (TXD)
TXD (Transmit Data)P0_3RPI Pin 10 (RXD)
CTS (Clear To Send)P0_5RPI Pin 11 (RTS)
RTS ( Ready To Send)P0_4RPI Pin 36 (CTS)

When using a Wemos as the flashing device, it’s safe to tie the two I/O pins together (D5 and D6) and connect them to the DD pin on the CC2530. It works fine. The P0_2 through P0_5 pins are used when you’re using the finished device, not when flashing (so you don’t need to connect them up).

Pinout for CC2530+CC2591 module

The above diagram shows the pin mappings on the CC2530+CC2591 module itself. Follow those numbers and the pins above to wire it up.

Pinout of Debug Header on CC2530 (not present on combined module)

This diagram shows the pinout of the debug header (which is not present on the CC2591). However, it does show which pins on the CC2591 marry up to what purposes on the debug header (which correspond to pins on the Wemos).

After this is done, you need to use CClib to flash the firmware.

Flashing the Z-Stack Firmware

Get the firmware from this link. You will also need to install Python 2.7 for your system. Once that’s done, install pyserial with;

pip install pyserial==3.0.1

Edit the firmware .hex you downloaded, and remove the second to last line (it won’t work with the flasher you’re using). Once that is done, connect your Wemos to your computer, and then from the Python directory in your CClib download, run;

python cc_info.py -p COM9

Assuming that COM9 is your Wemos. You should see output giving you data on the CC2530. If so, fantastic. Now flash it;

python cc_write_flash.py -e -p COM9 --in=YOURFIRMWAREHERE.hex

This will take an extremely long time. Several hours. But you should see progress fairly quickly. Just hang tight. Once that’s done, you have a coordinator!

Next post will deal with testing the coordinator out.

References and Links