Last active
October 11, 2016 16:19
-
-
Save raldred/c9e9a592e6ed341af6c060fcf26cbe23 to your computer and use it in GitHub Desktop.
Arduino WBus & SIM900
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//hacked together by bo herrmannsen 2016 | |
#include "wbus.h" | |
#include "SIM900.h" | |
#include <SoftwareSerial.h> | |
#include "sms.h" | |
SMSGSM sms; | |
char number[]="3921234567"; | |
char message[180]; | |
byte stat; | |
char pos; | |
char *p; | |
int i=0; | |
#define tx_line 18 //pin for TX | |
#define RESPONSE_TIMEOUT 500 | |
#define ERROR_DELAY 1000 | |
#define NACK_DELAY 5000 | |
#define ERROR_TMO_CHK_ADR 250 | |
#define ERROR_NACK 240 | |
byte rs232_byte; | |
byte bytes_count, cnt; | |
byte error, tries1, tries2; | |
byte msgbuffer[15], message_data[10], message_length; | |
bool keepalive = false; | |
bool flamecheck = false; | |
void setup() | |
{ | |
Serial.begin(9600); | |
if (gsm.begin(2400)) | |
Serial.println("\nstatus=READY"); | |
else Serial.println("\nstatus=IDLE"); | |
} | |
unsigned char checksum(unsigned char *buf, unsigned char len) | |
{ | |
//Serial.print("length ="); | |
//Serial.println(len,DEC); | |
unsigned char chk = 0; | |
for ( ; len != 0; len--) { | |
chk ^= *buf++; | |
} | |
//Serial.print("checksum = "); | |
//Serial.println(chk,HEX); | |
return chk; | |
} | |
//-------------------------------------------------------------------------------- | |
void send_Serial_byte(byte value) | |
{ | |
Serial1.write(value); | |
} | |
//-------------------------------------------------------------------------------- | |
byte read_Serial_byte(void) | |
{ | |
if (Serial1.available() > 0) | |
{ | |
rs232_byte = Serial1.read(); | |
return 1; | |
} | |
return 0; | |
} | |
//-------------------------------------------------------------------------------- | |
void msg_send(byte cmd) | |
{ | |
msgbuffer[0] = ((WBUS_CLIENT_ADDR << 4) | WBUS_HOST_ADDR); | |
msgbuffer[1] = message_length + 2; | |
msgbuffer[2] = cmd; | |
for (cnt = 0, bytes_count = 3; cnt < message_length; cnt++, bytes_count++) msgbuffer[bytes_count] = message_data[cnt]; | |
// make checksum | |
msgbuffer[bytes_count] = 0;//clear old checksum | |
msgbuffer[bytes_count++] = checksum(msgbuffer, bytes_count); | |
// Send message | |
Serial.print("Sending: "); | |
PrintHex8(msgbuffer, bytes_count); | |
for (cnt = 0; cnt < bytes_count; cnt++) send_Serial_byte(msgbuffer[cnt]); | |
Serial1.flush(); | |
// wait if any other transmission | |
// and purge all receptions | |
while (Serial1.available() > 0) | |
{ | |
delay(1); | |
byte waste = Serial1.read(); | |
} | |
} | |
//-------------------------------------------------------------------------------- | |
void PrintHex8(uint8_t *data, uint8_t length) // prints 8-bit data in hex with leading zeroes | |
{ | |
for (int i = 0; i < length; i++) { | |
Serial.print("0x"); | |
if (data[i] < 0x10) { | |
Serial.print("0"); | |
} | |
Serial.print(data[i], HEX); | |
Serial.print(" "); | |
} | |
} | |
//-------------------------------------------------------------------------------- | |
byte msg_recv(byte cmd, byte skip) | |
{ | |
Serial.print("recv: "); | |
message_data[0] = 0; | |
message_data[1] = 0; | |
message_data[2] = 0; | |
message_data[3] = 0; | |
message_data[4] = 0; | |
message_data[5] = 0; | |
message_data[6] = 0; | |
message_data[7] = 0; | |
message_data[8] = 0; | |
message_data[9] = 0; | |
Serial.print("recv: 2"); | |
bytes_count = 0; | |
unsigned long currentMillis = millis(); | |
unsigned long previousMillis = currentMillis; | |
do | |
{ | |
currentMillis = millis(); | |
if (read_Serial_byte() != 0) | |
{ | |
msgbuffer[bytes_count] = rs232_byte; | |
bytes_count++; | |
previousMillis = currentMillis; | |
} | |
} | |
while (currentMillis - previousMillis < RESPONSE_TIMEOUT && bytes_count < sizeof(msgbuffer)); | |
// | |
// check timeout | |
if (bytes_count == 0) | |
{ | |
// Timeout | |
Serial.println("Timeout"); | |
delay(500); | |
return ERROR_TMO_CHK_ADR; | |
} | |
Serial.print("\nReceived: "); | |
PrintHex8(msgbuffer, bytes_count); | |
// check checksum | |
if (checksum(msgbuffer, bytes_count) != 0) | |
{ | |
// Checksum error | |
Serial.println("Checksum error"); | |
return ERROR_TMO_CHK_ADR; | |
} | |
// check address | |
if (msgbuffer[0] != ((WBUS_HOST_ADDR << 4) | WBUS_CLIENT_ADDR)) | |
{ | |
// Incorrect address | |
Serial.println("Incorrect address"); | |
return ERROR_TMO_CHK_ADR; | |
} | |
// check validity | |
if (msgbuffer[2] != (cmd | 0x80)) | |
{ | |
// Request was rejected... | |
Serial.println("Request was rejected"); | |
message_length = 0; | |
return ERROR_NACK; | |
} | |
// copy info to data | |
message_length = msgbuffer[1] - 2 - skip; | |
bytes_count = 3 + skip; | |
for (cnt = 0; cnt < message_length; cnt++, bytes_count++) | |
{ | |
message_data[cnt] = msgbuffer[bytes_count]; | |
} | |
return 0; | |
} | |
//-------------------------------------------------------------------------------- | |
// | |
// Send a client W-Bus request and read answer from Heater. | |
// | |
void wb_io(byte cmd, byte skip) | |
{ | |
tries2 = 0; | |
do | |
{ | |
if (tries2 != 0) delay(NACK_DELAY); | |
tries1 = 0; | |
do | |
{ | |
if (tries1 != 0) delay(ERROR_DELAY); | |
SendBreak(50); | |
msg_send(cmd); | |
// receive reply | |
error = msg_recv(cmd, skip); | |
tries1++; | |
} | |
while (tries1 < 10 && error == ERROR_TMO_CHK_ADR); // timeout, bad checksum or invalid address | |
tries2++; | |
} | |
while (tries2 < 2 && error == ERROR_NACK); // request denied | |
} | |
void SendBreak(byte duration) | |
{ | |
Serial.println("\n**** BREAK SENT ****\n"); | |
Serial1.end(); // disable Serial1 transmission | |
pinMode(tx_line, OUTPUT); | |
digitalWrite(tx_line, 0); // set low the tx pin | |
delay(duration); // wait 25 ms | |
digitalWrite(tx_line, 1); // set high the tx pin | |
delay(duration); | |
Serial1.begin(2400, SERIAL_8E1); // re-enable Serial1 transmission | |
delay(25); | |
} | |
//-------------------------------------------------------------------------------- | |
// | |
// Turn heater on for time minutes | |
// | |
void turnOn(byte time) | |
{ | |
message_data[0] = time; | |
message_length = 1; | |
wb_io(WBUS_CMD_ON_PH, 0); | |
keepalive=true; | |
message[0]='\0'; | |
strcat(message," Starting "); | |
sms.SendSMS(number,message); | |
} | |
//-------------------------------------------------------------------------------- | |
// | |
// Turn heater off | |
// | |
void turnOff(void) | |
{ | |
message_length = 0; | |
wb_io(WBUS_CMD_OFF, 0); | |
keepalive=false; | |
flamecheck=false; | |
message[0]='\0'; | |
strcat(message," Stopping "); | |
sms.SendSMS(number,message); | |
} | |
//-------------------------------------------------------------------------------- | |
// | |
// keepAlive - poll the heater | |
// | |
void keepAlive() | |
{ | |
message_data[0] = WBUS_CMD_ON_PH; // polling (keep-alive) | |
message_data[1] = 0; | |
message_length = 2; | |
wb_io(WBUS_CMD_CHK, 0); | |
if (error != 0) return; | |
} | |
//-------------------------------------------------------------------------------- | |
// | |
// get status 2 | |
// | |
void get_status2(void) | |
{ | |
message_data[0] = QUERY_STATUS2; // status 2 - level of devices | |
message_length = 1; | |
wb_io(WBUS_CMD_QUERY, 1); | |
if (error != 0) | |
{ | |
return; | |
} | |
unsigned char glowplug_percentage = message_data[STA2_GP] ; | |
unsigned char fuelpump_percentage = message_data[STA2_FP] ; | |
unsigned char airfan_percentage = message_data[STA2_CAF] ; | |
unsigned char circpump_percentage = message_data[STA2_CP] ; | |
message[0]='\0'; | |
strcat(message,"Plug "); | |
strcat(message, glowplug_percentage); | |
strcat(message," FPump "); | |
strcat(message, fuelpump_percentage); | |
strcat(message," Fan "); | |
strcat(message, airfan_percentage); | |
strcat(message," CPump "); | |
strcat(message, circpump_percentage); | |
sms.SendSMS(number,message); | |
} | |
//-------------------------------------------------------------------------------- | |
// | |
// get status | |
// | |
void get_status(void) | |
{ | |
message_data[0] = QUERY_SENSORS; // sensors - temperature, volts, flame detection, glow plug resistance | |
message_length = 1; | |
wb_io(WBUS_CMD_QUERY, 1); | |
if (error != 0) return; | |
int temp = message_data[SEN_TEMP] - 50; | |
float voltage = ((message_data[SEN_VOLT] * 256) + message_data[SEN_VOLT + 1]) ;//in millivolts | |
int volt = voltage; | |
int FlameOn = message_data[SEN_FD]; | |
int watts = ((message_data[SEN_HE] * 256) + message_data[SEN_HE + 1]); | |
int resistance = ((message_data[SEN_GPR] * 256) + message_data[SEN_GPR + 1]); | |
message[0]='\0'; | |
strcat(message,"Temp "); | |
strcat(message, temp); | |
strcat(message," Volt "); | |
strcat(message, volt); | |
strcat(message," Flame "); | |
strcat(message, FlameOn); | |
strcat(message," Watts "); | |
strcat(message, watts); | |
strcat(message," Ohm "); | |
strcat(message, resistance); | |
sms.SendSMS(number,message); | |
} | |
//-------------------------------------------------------------------------------- | |
// | |
// check flame | |
// | |
void check_flame(void) | |
{ | |
message_data[0] = QUERY_SENSORS; // sensors - temperature, volts, flame detection, glow plug resistance | |
message_length = 1; | |
wb_io(WBUS_CMD_QUERY, 1); | |
if (error != 0) return; | |
int temp = message_data[SEN_TEMP] - 50; | |
float voltage = ((message_data[SEN_VOLT] * 256) + message_data[SEN_VOLT + 1]) ;//in millivolts | |
int volt = voltage; | |
int FlameOn = message_data[SEN_FD]; | |
int watts = ((message_data[SEN_HE] * 256) + message_data[SEN_HE + 1]); | |
int resistance = ((message_data[SEN_GPR] * 256) + message_data[SEN_GPR + 1]); | |
if (FlameOn = 1 ) | |
{ | |
if (flamecheck == false) | |
{ | |
message[0]='\0'; | |
strcat(message,"Temp "); | |
strcat(message, temp); | |
strcat(message," Flame "); | |
strcat(message, FlameOn); | |
flamecheck=true; | |
sms.SendSMS(number,message); | |
} | |
} | |
} | |
void loop() | |
{ | |
number[0]='\0'; | |
pos=sms.IsSMSPresent(SMS_UNREAD); | |
Serial.println((int)pos); | |
if((int)pos>0&&(int)pos<=20) { | |
Serial.print("Sms detected at pos "); | |
Serial.println((int)pos); | |
message[0]='\0'; | |
//stat=sms.GetAuthorizedSMS((int)pos,number,message,180,8,10); | |
stat=sms.GetAuthorizedSMS((int)pos,number,strlen(number),message,180,8,10); | |
if(stat==GETSMS_AUTH_SMS) { | |
p=strstr(message,"Start"); | |
if(p) { | |
Serial.println("starting"); | |
turnOn(30);//30 mins | |
} | |
p=strstr(message,"stop"); | |
if(p) { | |
Serial.println("Stopping"); | |
turnOff(); | |
} | |
p=strstr(message,"status1"); | |
if(p) { | |
Serial.println("Getting status 1 data"); | |
get_status(); | |
Serial.println("Sending status 1 data via sms"); | |
} | |
p=strstr(message,"status2"); | |
if(p) { | |
Serial.println("Getting status 2 data"); | |
get_status2(); | |
Serial.println("Sending status 2 data via sms"); | |
} | |
delay(5000); | |
if (keepalive == true) keepAlive(); | |
if (flamecheck == false) check_flame(); | |
} | |
sms.DeleteSMS((int)pos); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment