Skip to content

Instantly share code, notes, and snippets.

@raldred
Last active October 11, 2016 16:19
Show Gist options
  • Save raldred/c9e9a592e6ed341af6c060fcf26cbe23 to your computer and use it in GitHub Desktop.
Save raldred/c9e9a592e6ed341af6c060fcf26cbe23 to your computer and use it in GitHub Desktop.
Arduino WBus & SIM900
//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