MQTT, Arduino, Old Ammeters and Bandwidth Monitoring

Thanks to some help from @knolleary the arduino pubsub library now works with mosquitto. I have now completed my bandwidth monitor project which I want to document in this post.

I have mentioned in previous posts that I use various scripts and sensors to feed data into the open source MQTT broker mosquitto. Currently all data is posted to pachube, rather than everything being online I decided I wanted some physical feedback. Having made an impulse buy of two vintage Ferranti ammeters using these to display some of my data seemed like obvious answer! The code on the arduino basically just displays a number passed by MQTT on the meter and therefore could be applied to any measurement one cared to choose.

The basic idea of this system is to monitor the current internet speed usage and display it on the ammeter. The system is based around an arduino with ethernet shield which acts as an MQTT client, this subscribes to the downstream bandwidth topic on my MQTT broker, receives the messages and changes the level of a PWM output pin on the arduino which causes the meter to show the appropriate level. The meter displays the current through a resistor which is varied by the PWM signal from the arduino. The reading on the meter corresponds to the current internet speed usage as a percentage of the overall theoretical available bandwidth.

The Arduino Code

As this is quite well commented I won’t go through it, but it serves as a good example of how to receive MQTT messages using an arduino:

#include <Ethernet.h>

#include <PubSubClient.h>


//Setup network connection

byte mac[] = {  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { <arduino ip> };
byte subnet[] = {<subnet>};
byte gateway[] = {<router ip>};

//MQTT Broker

byte server[] = {<mqtt broker (mosquitto/RSMB)>};
int port = 1883;
//Meter output spin

int meterPin = 9;

//Set initial bandwidth

float out = 0;

//MQTT client setup

PubSubClient client(server, port, callback);

//Add callback for when a message is recieved

//

// Takes bandwidth as 4 digit number e.g 44 = 0044

void callback(char* topic, byte* payload,int length) {
  //reset value

  out=0;

  //convert receieved byte array into number

  for(int i=0;i<4;i++)
  {
    //get the byte

    byte ardValue = payload[i];
    //multiply it by 1/10/100 or 1000

    double tens = pow(10,(3-i));
    //convert the byte to either 1/10/100/1000

    float ardOut = tens * (ardValue-48);
    //add to total output

    out +=ardOut;
  }

  //scale number between 0-4000 to 0-255 for output

  out = map(out, 0, 4000, 0, 255);

  //print result to serial port for debugging

  Serial.println(out);

  //write output to meter

  analogWrite(meterPin, out);
}

//setup method

void setup()
{
  //start ethernet connection

  Ethernet.begin(mac, ip, gateway, subnet);

  //start serial connection for debugging

  Serial.begin(9600);

  //connect to MQTT Broker

  client.connect(&quot;arduino&quot;);

  //Subscribe to topic bandDown

  client.subscribe(&quot;bandDown&quot;);
}

//main loop

void loop()
{
  //Tell the MQTT broker we're still here

  client.loop();
}

The PHP script that provides the bandwidth data resides on my sheevaplug and queries my router for an XML file with the appropriate details, I talked about this in a previous post.