ESP8266 WiFi indicator with WS2812 LED

I had some ESP8266 modules and WS2812 LEDs laying around, that were only collecting dust, so I decided to make a little, maybe useless, project.

It simply shows the average WiFi RSSI by scanning for networks continuously, adding up the RSSIs and dividing them by the number of found networks. Since I’ve used the Adafruit WS2812 library together with the ESP8266 libs for Arduino, I had a prebuilt function, that can be fed with 0-255 to set a color. As the function name ‘Wheel();’ already states, it cycles through the colors in a circle, so we only need around half of that range. After some tests, I found that adding 100 and multiplying the value by 2.2 works quite ok.

So, you say, this is quite boring for such a powerful microcontroller? You’re right! I decided to add an interrupt to the ‘flash’-button, that is on the dev-board and can be used as a normal GPIO-button. Once pressed, the LED will blink as often as many networks have been found. Afterwards it will show the color for the strongest and then for the weakest signal. The purpose of the serial output was actually just for debugging, but I left it there, so you I can still check the values at any time.

After testing it at home, I finally went out in the wild to test it at a place with a huge amount of networks (60+). I figured out, while the LED was blinking, the controller got reset after ~17 blinks. This was done by the watchdog, that couldn’t be turned off at that time (maybe the lib got an update now). So I decided to feed the not-so-cute-litte dog every blink with ‘ESP.wdtFeed();’.

Here is an example video:

And of course the code:

#include "ESP8266WiFi.h"
#include <Adafruit_NeoPixel.h>

#define PIXEL_PIN	14
#define PIXEL_COUNT	1

#define cfact 2.2

Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, NEO_GRB + NEO_KHZ400);

// function prototypes
uint32_t Wheel(byte);
void wificount_ISR(void);

// global variables
int n = 0, hrssicol = 0, lrssicol = 0;

void setup() {
	pinMode(14, OUTPUT);
	digitalWrite(14, LOW);
	Serial.begin(115200);
	WiFi.mode(WIFI_STA);
	WiFi.disconnect();
	strip.begin();
	strip.show();
	attachInterrupt(digitalPinToInterrupt(0), wificount_ISR, FALLING);
	delay(100);
}

void loop() {
	// number of networks
	n = WiFi.scanNetworks();

	// variables for highest and lowest rssi value
	int hrssi = -120;
	int lrssi = 0;

	// temp. variable for sum of rssi values
	int m = 0;

	if (n == 0) {
		Serial.println("no networks found");
		for ( int i = 0; i < 5; i++ ) {
			strip.setPixelColor(0, 127, 0, 0);
			strip.show();
			delayMicroseconds(200000);
			strip.setPixelColor(0, 0);
			strip.show();
			delayMicroseconds(200000);
		}
	} else {
		Serial.println("-------------------------");
		for ( int i = 0; i < n; i++ ) {
			m += WiFi.RSSI(i);

			// finding highest value
			if ( WiFi.RSSI(i) > hrssi) {
				hrssi = WiFi.RSSI(i);
			}

			// finding lowest value
			if ( WiFi.RSSI(i) < lrssi) {
				lrssi = WiFi.RSSI(i);
			}

			// infos via serial
			Serial.print(i + 1);
			Serial.print(": ");
			Serial.print(WiFi.SSID(i));
			Serial.print(" (");
			Serial.print(WiFi.RSSI(i));
			Serial.print(")");
			Serial.println((WiFi.encryptionType(i) == ENC_TYPE_NONE)?" ":"*");
			ESP.wdtFeed();
		}

		// calulating color value by shifting average rssi up by 100 and multiplying by a factor for spreading out the range
		int rssicol = ( (m/n) + 100 ) * cfact;

		// infos via serial
		Serial.print("high RSSI: ");
		Serial.println(hrssi);
		Serial.print("high RSSI: ");
		Serial.println(lrssi);

		// set color values for ISR
		hrssicol = ( hrssi + 100 ) * cfact;
		lrssicol = ( lrssi + 100 ) * cfact;

		// infos via serial
		Serial.println("-------------------------");
		Serial.print("average RSSI: ");
		Serial.println(m/n);
		Serial.print("color: ");
		Serial.println(rssicol);
		Serial.print("high RSSI color: ");
		Serial.println(hrssicol);
		Serial.print("low RSSI color: ");
		Serial.println(lrssicol);

		// set color finally
		strip.setPixelColor(0, Wheel(rssicol) );
		strip.show();

		Serial.println("");
	}
}

// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
	WheelPos = 255 - WheelPos;
	if(WheelPos < 85) {
	 return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
	} else if(WheelPos < 170) {
		WheelPos -= 85;
	 return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
	} else {
	 WheelPos -= 170;
	 return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
	}
}

void wificount_ISR() {
	Serial.println("ISR BEGIN");

	// turn off LED
	strip.setPixelColor(0, 0);
	strip.show();

	delayMicroseconds(500000);

	if (n == 0) {
		Serial.println("no networks found");
	} else {
		// blink n times, where n is number of networks
		for ( int i = 0; i < n; i++ ) {
			strip.setPixelColor(0, 127, 127, 127);
			strip.show();
			delayMicroseconds(150000);
			strip.setPixelColor(0, 0);
			strip.show();
			delayMicroseconds(150000);
			ESP.wdtFeed();
		}

		delayMicroseconds(800000);

		// show color for highest value
		strip.setPixelColor(0, Wheel(hrssicol) );
		strip.show();
		delayMicroseconds(1000000);
		strip.setPixelColor(0, 0);
		strip.show();
		delayMicroseconds(200000);

		// show color for lowest value
		strip.setPixelColor(0, Wheel(lrssicol) );
		strip.show();
		delayMicroseconds(1000000);
		strip.setPixelColor(0, 0);
		strip.show();
		delayMicroseconds(200000);
	}
	Serial.println("ISR END");
}