Hi novice,
I haven't done a write-up yet because the project isn't finished. I have a nice old brass meter from an old ship that I'm going to mount the project in (without the oled display), along with a smaller slave meter for upload status.
Here's the sketch at the moment:
#include <Wire.h>
#include <NewSoftSerial.h>
void sendChar(char ascii);
NewSoftSerial wfSerial(11, 12);
#define OLED_address 0x3c
extern unsigned char myFont[][8];
uint8_t oled_row=0; // Current oled write row
const uint8_t meterPin = 9; // analog meter pin
#define WF_MAX_MSG_SIZE 64
#define WF_EOM 255 /* End of message marker character */
#define NUM_STEPS 19 /* Number of steps when moving meter */
char buf[WF_MAX_MSG_SIZE];
int ind=0;
int step;
int meterMin=0;
int meterMax=0;
void setup()
{
Serial.begin(9600);
Serial.println("Starting");
wfSerial.begin(9600);
Wire.begin();
init_OLED();
delay(10);
clear_display();
delay(50);
sendcommand(0x20); //Set Memory Addressing Mode
sendcommand(0x02); //Set Memory Addressing Mode ab Page addressing mode(RESET)
sendcommand(0xa6); //Set Normal Display (default)
setXY(0,0);
sendStr("Bandwidth 1.0\n\r");
incRow();
pinMode(meterPin, OUTPUT);
/* Test meter */
int ind;
for (ind=0; ind<255; ind+=10) {
analogWrite(meterPin, ind);
delay(100);
}
analogWrite(meterPin, 255);
delay(1000);
for (ind=250; ind>0; ind-=10) {
analogWrite(meterPin, ind);
delay(100);
}
analogWrite(meterPin, 0);
}
void loop()
{
/* Currently stepping meter towards meterMax? */
if (step) {
/* Take next step */
delay(100);
analogWrite(meterPin, map(step, NUM_STEPS, 0, meterMin, meterMax));
step--;
}
/* Check for UDP data */
if (wfSerial.available() > 0) {
uint8_t ch = wfSerial.read();
/* Got end of message marker? */
if (ch != WF_EOM) {
/* collect all the input in the buffer */
if (ind < (WF_MAX_MSG_SIZE-1)) {
buf[ind++] = ch;
}
} else {
/* Got a full message, deal with it
* Message format is a string "%6.2f KB/s",
* e.g. "1038.27 KB/s"
* Note: Currently the first character in the string
* is a carriage return '\r' so the oled display line
* resets to column 0 before printing the string.
*/
buf[ind] = 0; // Null terminate the buffer
ind = 0; // reset ind for next buffer
/* Update Oled with new rate */
sendStr(buf);
/* Work out where the meter needs to move to,
* have it move in a series of smaller steps so
* the movement is smooth. Max is 2047 (5V).
*/
long kbps = atoi(buf);
meterMin = meterMax; /* Old position */
meterMax = map(kbps, 0, 2047, 0, 255); /* New position */
step = NUM_STEPS; /* Move there in this many steps */
#ifdef DEBUG
Serial.print(kbps,DEC);
Serial.print(" -> ");
Serial.println(meterMax,DEC);
#endif
}
}
}
/*
* OLED commands
*/
//=======================
void sendcommand(unsigned char com)
{
Wire.beginTransmission(OLED_address); //begin transmitting
Wire.send(0x80);//command mode
Wire.send(com);
Wire.endTransmission(); // stop transmitting
}
//==================================
void clear_display(void)
{
unsigned char i,k;
for(k=0; k<8; k++) {
setXY(k,0);
for(i=0; i<128; i++) {
sendByte(0);
}
}
}
//===================================
void sendByte(unsigned char data)
{
Wire.beginTransmission(OLED_address); // begin transmitting
Wire.send(0x40);//data mode
Wire.send(data);
Wire.endTransmission(); // stop transmitting
}
void incRow()
{
oled_row++;
if (oled_row > 7) {
/* scroll up one line */
oled_row = 0;
setRow(oled_row);
} else {
setRow(oled_row);
}
}
void setRow(uint8_t row)
{
Serial.print("setRow(");
Serial.print(row,DEC);
Serial.println(")");
sendcommand(0xb0+row); //set page address
oled_row = row;
}
void setCol(uint8_t col)
{
sendcommand(0x00+(8*col&0x0f)); //set low col address
sendcommand(0x10+((8*col>>4)&0x0f)); //set high col address
}
//===================================
void setXY(unsigned char row,unsigned char col)
{
Serial.println("setXY()");
setRow(row);
setCol(col);
}
//==================================
void sendChar(char ascii)
{
unsigned char i=0;
for(i=0;i<8;i++) {
sendByte(myFont[ascii-0x20][i]);
}
}
//==================================
void sendStr(const char *string)
{
#ifdef DEBUG
Serial.print("sendStr(\"");
Serial.print(string);
Serial.println("\")");
#endif
while(*string) {
if (*string == '\n') {
incRow();
} else if (*string == '\r') {
setCol(0);
} else if (*string >= 0x20) {
sendChar(*string);
}
*string++;
}
}
//=================================
void init_OLED(void)
{
sendcommand(0xae); //display off
delay(50);
sendcommand(0xaf); //display on
delay(50);
}
It also uses the attached data.c file for the oled font (from SeeedStudio).
The oled display is a 128x64 grove module from SeeedStudio with an I2C interface (i.e. only needs two pins to drive it). The oled functions in the sketch are mostly straight from the SeedStudio sample sketch. The meter is a 5V analog meter from SparkFun.
I have a python script running on a machine collecting the upload and download byte counts from my Dlink router via SNMP and then sending the Rx rate via to the WiFly via a UDP message every 2 seconds. I'm considering having the Arduino actually do the SNMP queries directly to the Dlink router instead, but it will be a bit of a pain to build the query and decode the response - maybe I can cheat and just use a canned query message and pull the result from a hard-coded offset in the response.
I configured the WiFly by switching the XBee shield to hardware serial mode and USB UART mode, then used the serial monitor from the Arduino IDE and sent the "$$$" string to switch the WiFly to config mode (no CR/NL for this). I set the following options:
set ip dhcp 1 // enable DHCP mode
set wlan join 1 // automatically connect to the wireless network
set wlan ssid <my wireless network SSID>
set wlan phrase <my WPA password>
set wlan hide 1 // hide my WPA password
set wlan chan 0 // scan all channels to find network
set ip proto 1 // UDP only (this also disables telnet for config)
set ip flags 0x40 // enable UDP pairing mode
set ip host 0.0.0.0 // for pairing mode
set ip localport 2042 // port to accept UDP messages on
save // save the new config
reboot
data.c (4.09 KB)