#include <NewSoftSerial.h>
#include <etherShield.h>
#include <LiquidCrystal.h>
//#define DEBUG
#ifdef DEBUG
#define DEBUG_PRINT(x) Serial.print(x)
#define DEBUG_PRINTLN(x) Serial.println(x)
#else
#define DEBUG_PRINT(x)
#define DEBUG_PRINTLN(x)
#endif
#include <string.h> // for strlen();
// Define the pins used for the software serial port. Note that we won't
// actually be transmitting anything over the transmit pin.
#define rxPin 3
#define txPin 300
// LED onboard
#define ledPin 13
// Set up the serial port
NewSoftSerial currentcost(rxPin, txPin);
char stringData[16];
int content_length;
const char iphdr[] PROGMEM ={
0x45,0,0,0x82,0,0,0x40,0,0x20};
// MAC and IP have to be unique in your local area network.
static uint8_t mymac[6] = {
0x11,0x22,0x33,0x44,0x55,0x66}; // The MAC address of your arduino.
static uint8_t myip[4] = {
192,168,0,99}; // The IP address of your arduino.
static uint16_t srcport = 6407;
// Destination settings
static uint8_t destmac[6] = {
0x01,0x23,0x45,0x67,0x89,0xAB}; // The MAC address of your router.
static uint8_t broadcastip[4] = {
1,2,3,4 }; // The IP address of your server.
// Destination Port 52240
#define DEST_PORT_L 0x10
#define DEST_PORT_H 0xCC
char startPwr[] = "<ch1><watts>";
char startTmpr[] = "<tmpr>";
char endChar = '<';
char readChar = 0xFF;
int sizePwr = sizeof(startPwr)-1;
int sizeTmpr = sizeof(startTmpr)-1;
int statePwr = sizePwr;
int stateTmpr = sizeTmpr;
int newstate = 0;
long PwrNum = 0;
double TmprDouble = 0;
char Pwr[16] = "";
char Tmpr[16] = "";
// Packet buffer, must be big enough to packet and payload
#define BUFFER_SIZE 150
static uint8_t buf[BUFFER_SIZE+1];
EtherShield es=EtherShield();
LiquidCrystal lcd(8, 11, 9, 4, 5, 6, 7);
struct UDPPayload {
uint32_t time;
long power;
double temperature;
};
UDPPayload udpPayload;
char ready = 0;
void setup(void) {
// Display welcome message on LCD screen.
lcd.begin(16, 2);
lcd.print("Current Cost+");
// Define pin modes for tx and rx pins.
pinMode(rxPin, INPUT);
pinMode(txPin, OUTPUT);
// Set the data rate for the NewSoftSerial port.
currentcost.begin(57600);
// Set the data rate for the hardware serial port
Serial.begin(115200);
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, LOW);
// Initialise the UDP payload
udpPayload.time = millis();
udpPayload.temperature = 0;
udpPayload.power = 0;
init_ethershield();
}
void loop(void) {
readChar = currentcost.read();
if (readChar > 31) {
stateTmpr = parseDataTmpr(stateTmpr, readChar);
if (stateTmpr < 0) {
Tmpr[abs(stateTmpr)-1] = readChar;
}
statePwr = parseDataPwr(statePwr, readChar);
if (statePwr < 0) {
Pwr[abs(statePwr)-1] = readChar;
}
}
else if (readChar == 13) {
PwrNum = atol(Pwr);
TmprDouble = strtod(Tmpr,NULL);
// Print to the serial port.
Serial.flush();
Serial.print("Pwr:");
Serial.print(PwrNum);
Serial.print("Tmpr:");
Serial.println(TmprDouble);
Serial.flush();
// Write to the LCD screen.
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Power: ");
lcd.print(PwrNum);
lcd.print("W");
lcd.setCursor(0, 1);
lcd.print("Temp: ");
lcd.print(TmprDouble);
lcd.print("C");
digitalWrite(ledPin, LOW);
// Indicate that data is ready to be sent.
ready = 1;
}
if (ready == 1) {
ready = 0;
digitalWrite(ledPin, HIGH);
sprintf(stringData, " %lu, %lf", PwrNum, TmprDouble);
content_length = strlen(stringData);
Serial.flush();
DEBUG_PRINTLN(stringData);
Serial.flush();
udpPayload.time = millis();
udpPayload.temperature = TmprDouble;
udpPayload.power = PwrNum;
broadcastData();
digitalWrite(ledPin, LOW);
}
}
void broadcastData( void ) {
uint8_t i=0;
uint16_t ck;
// Setup the MAC addresses for ethernet header
while(i<6){
buf[ETH_DST_MAC +i]=destmac[i]; // Broadcsat address
buf[ETH_SRC_MAC +i]=mymac[i];
i++;
}
buf[ETH_TYPE_H_P] = ETHTYPE_IP_H_V;
buf[ETH_TYPE_L_P] = ETHTYPE_IP_L_V;
es.ES_fill_buf_p(&buf[IP_P],9,iphdr);
// IP Header
buf[IP_TOTLEN_L_P]=28+sizeof(UDPPayload);
buf[IP_PROTO_P]=IP_PROTO_UDP_V;
i=0;
while(i<4){
buf[IP_DST_P+i]=broadcastip[i];
buf[IP_SRC_P+i]=myip[i];
i++;
}
es.ES_fill_ip_hdr_checksum(buf);
buf[UDP_DST_PORT_H_P]=DEST_PORT_H;
buf[UDP_DST_PORT_L_P]=DEST_PORT_L;
buf[UDP_SRC_PORT_H_P]=10;
buf[UDP_SRC_PORT_L_P]=srcport; // lower 8 bit of src port
buf[UDP_LEN_H_P]=0;
buf[UDP_LEN_L_P]=8+sizeof(UDPPayload); // fixed len
// zero the checksum
buf[UDP_CHECKSUM_H_P]=0;
buf[UDP_CHECKSUM_L_P]=0;
// Copy the data:
i=0;
// Most fields are zero, here we zero everything and fill later.
uint8_t* b = (uint8_t*)&udpPayload;
while(i< sizeof( UDPPayload ) ){
buf[UDP_DATA_P+i]=*b++;
i++;
}
// Create correct checksum.
ck=es.ES_checksum(&buf[IP_SRC_P], 16 + sizeof( UDPPayload ),1);
buf[UDP_CHECKSUM_H_P]=ck>>8;
buf[UDP_CHECKSUM_L_P]=ck& 0xff;
es.ES_enc28j60PacketSend(42 + sizeof( UDPPayload ), buf);
}
int parseDataTmpr(int oldstate, char chr) {
newstate = oldstate;
if (newstate > 0) {
if (chr == startTmpr[sizeTmpr-newstate]) {
newstate--;
}
else {
newstate = sizeTmpr;
}
}
else if (newstate <= 0) {
newstate--;
if (chr == endChar) {
newstate = sizeTmpr;
}
}
return newstate;
}
int parseDataPwr(int oldstate, char chr) {
newstate = oldstate;
if (newstate > 0) {
if (chr == startPwr[sizePwr-newstate]) {
newstate--;
}
else {
newstate = sizePwr;
}
}
else if (newstate <= 0) {
newstate--;
if (chr == endChar) {
newstate = sizePwr;
}
}
return newstate;
}
//*****************************************************************************
//
// Standard NUElectronics EtherShield Functions, No Changes Necessary
//
//*****************************************************************************
void init_ethershield() {
// initialize enc28j60
es.ES_enc28j60Init(mymac);
es.ES_enc28j60clkout(2); // change clkout from 6.25MHz to 12.5MHz
delay(10);
/* Magjack leds configuration, see enc28j60 datasheet, page 11 */
// LEDA=greed LEDB=yellow
// 0x880 is PHLCON LEDB=on, LEDA=on
// enc28j60PhyWrite(PHLCON,0b0000 1000 1000 00 00);
es.ES_enc28j60PhyWrite(PHLCON,0x880);
delay(500);
// 0x990 is PHLCON LEDB=off, LEDA=off
// enc28j60PhyWrite(PHLCON,0b0000 1001 1001 00 00);
es.ES_enc28j60PhyWrite(PHLCON,0x990);
delay(500);
// 0x880 is PHLCON LEDB=on, LEDA=on
// enc28j60PhyWrite(PHLCON,0b0000 1000 1000 00 00);
es.ES_enc28j60PhyWrite(PHLCON,0x880);
delay(500);
// 0x990 is PHLCON LEDB=off, LEDA=off
// enc28j60PhyWrite(PHLCON,0b0000 1001 1001 00 00);
es.ES_enc28j60PhyWrite(PHLCON,0x990);
delay(500);
// 0x476 is PHLCON LEDA=links status, LEDB=receive/transmit
// enc28j60PhyWrite(PHLCON,0b0000 0100 0111 01 10);
es.ES_enc28j60PhyWrite(PHLCON,0x476);
delay(100);
// init the ethernet/ip layer:
es.ES_init_ip_arp_udp_tcp(mymac,myip,80);
}