Luca SevàMichele ValentiniMassimiliano
Published © GPL3+

How to Create BLE-WiFi Range Extender for T-Skin

We wanted to increase the communication range of the Tactigon Skin so we could use it over longer distances than BLE can offer.

IntermediateFull instructions provided2 hours1,252

Things used in this project

Hardware components

The Tactigon Skin (T-SKIN)
The Tactigon Skin (T-SKIN)
Raspberry Pi Zero Wireless
Raspberry Pi Zero Wireless
NodeMCU ESP8266 Breakout Board
NodeMCU ESP8266 Breakout Board
Adafruit Bluefruit LE UART Friend - Bluetooth Low Energy (BLE)

Software apps and online services

Arduino IDE
Arduino IDE


Read more



This code is flashed onto the NodeMCU.
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

//UDP handle
WiFiUDP Udp;
unsigned int UDP_Port = 5000;
char* UDP_IP = ""; //IP address of the RECEIVER
char PacketBuffer[1024]; //Buffer used for UDP data

//Wifi handle
const char* ssid = "YOUR_SSID"; 
const char* password = "YOUR_PASSWORD";
IPAddress ip(192, 168, 4, 2); //set a static IP for this device
IPAddress gateway(192, 168, 4, 1);
IPAddress subnet(255, 255, 255, 0);

bool flag = false; //to handle complete read of BLE data
int count = 0; //counter for checking correct length of received buffer from BLE, starts from 0 to 19

void setup() {
	memset(&PacketBuffer, (char)0, 1024); //set all buffer to 0
	pinMode(LED_BUILTIN, OUTPUT); //LOW = WiFi connected; HIGH = WiFi not connected
	digitalWrite(LED_BUILTIN, HIGH);
	Serial.begin(115200); //BLE serial
	WiFi.config(ip, gateway, subnet);
	WiFi.mode(WIFI_STA); //station mode
	WiFi.begin(ssid, password);
	Serial.print("Wait for WiFi");
	//wait for wireless connection
	while (WiFi.status() != WL_CONNECTED) {
	digitalWrite(LED_BUILTIN, LOW);
	Serial.println("WiFi connected");
	Serial.println("IP address: " + WiFi.localIP().toString());
	Udp.begin(UDP_Port); //initialize UDP

void loop() {
	//if wireless connection drops, try to reconnect to it
	while (WiFi.status() != WL_CONNECTED) {
		digitalWrite(LED_BUILTIN, HIGH);

	digitalWrite(LED_BUILTIN, LOW);
	if (Serial.available()) {
		//read one char at the time and store it to che progressive 'count' position in the buffer array[count], 1);
		//checking for carriage return and line feed chars 
		//replace carriage return (if for any reasons is present) with whitespace to avoid complications in the buffer processing by the receiver
		if (PacketBuffer[count] == '\r') PacketBuffer[count] = ' '; 
		else if (PacketBuffer[count] == '\n') {
			//at this point the one buffer from BLE serial is completely processed
			PacketBuffer[count] = (char)0; 
			count = 0; //reset counter
			flag = true; //complete data
		else {
			//increment counter for next char read

	if (flag) {
		//start send data from [1] and not [0] due to how data is sent by the T-skin.
		//the data in [0] is treated by a serial read as a terminator char (char)0.
		//if this data ends up in the buffer that we send the calid data after that char will be ignored
		//sending data from 2nd element is less time consuming that shifting all buffer
		//Serial.println(&PacketBuffer[1]); //for debug
		//here we send via UDP the data from BLE
		Udp.beginPacket(UDP_IP, UDP_Port);
		flag = false; //reset flag for next buffer
		memset(PacketBuffer, (char)0, 1024); //set all buffer to 0

This code will automatically run at bootup on the Raspberry Pi Zero W.
#!/usr/bin/env python
#To run this script at boot you have te add the following to the /etc/rc.local file in sudo mode
#sudo python /path_to_this_script/
#before the exit 0 directive
import os
import sys
import socket
import serial
import time

UDP_PORT = 5000
UDP_IP = '' #IP address of the machine to whick this script will run
#small delay to ensure that everithing started up

port = serial.Serial("/dev/ttyGS0", baudrate=115200, timeout=0.1)

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind((UDP_IP, UDP_PORT))

while ((port.in_waiting) <= 0):
    data, addr = sock.recvfrom(1024) #store received data
    #print(data) #for debug
    port.write(data + '\n') #write received data from UDP to the emulated serial port
#if the input buffer of the serial port is NOT empty that means that the shutdown command has been received from the PC
os.system("shutdown now -h")


Luca Sevà

Luca Sevà

8 projects • 8 followers
Michele Valentini

Michele Valentini

20 projects • 51 followers
From Pepper growing to CNC milling, i don't like to waste time sleeping


28 projects • 102 followers
I'm an engineer and I like robotics, embedded systems and linux. I spent a lot of time in automation and firmware development.