I’ve made myself a rough Arduino based controller for a fan that I already had lying around. While I haven’t actually wired it into the fan yet, bench testing suggests that it will mimic the existing controls pretty well - with a push button to cycle between power levels and a push button to control oscillation (on or off) I also have a DS18B20 temperature connected to the Arduino, but so far I’m not doing anything with the temperature data.
Now for the need to unnecessarily over complicate things. Most of my home automation devices are connected to HA via ZigBee (ZHA) using an XBee connected to my HA machine via USB using a Grove development board. I also have a couple of extra XBees…
So far I have managed to connect an XBee to the Arduino and communicate with another one in coordinator mode (so far just one way communication) using the Arduino serial connection. What I would really like to do though is connect to HA, using ZHA to give me the option to automate my fan, and use the connected temperature sensor within HA too. Unfortunately I’ve run out of talent as far as that bit goes.
I want to do this with the existing hardware I have, and have no interest in doing this with an ESP device, using WiFi. I have no desire to add any extra WiFi devices to my network.
I’ve looked here:
Building own zigbee device using arduino + zigbee shield which ended up as a WiFi discussion.
Here:
Zigbee Tradfri control almost anything - which doesn’t use the same hardware as I’m using
and I’ve tried using this:
however, using that I can’t get anything to appear on the console of the coordinator XBee so i’m doing it wrong I guess.
Current Arduino code is this: (I know it’s probably horrifically inefficient and messy, sorry)
/********************************************************************/
//libraries
#include <OneWire.h>
#include <DallasTemperature.h>
#include <XBee.h>
#include <SoftwareSerial.h>
/********************************************************************/
// DS18B20 Setup
#define ONE_WIRE_BUS 3
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);// Pass our oneWire reference to Dallas Temperature.
/********************************************************************/
// constants
const int pwrButtonPin = 6; // the number of the power button pin
const int oscButtonPin = 7; // the number of the oscillation button
const int offPin = 13; // Power off LED pin
const int pw1Pin = 12; // Level 1 SSD/LED pin
const int pw2Pin = 11; // Level 2 SSD/LED pin
const int pw3Pin = 10; // Level 3 SSD/LED pin
const int oscPin = 9; // Oscillation SSD/LED pin
/********************************************************************/
// variables
int cycles = 0;
int pwrButtonState = 0;
int oscButtonState = 0;
int powerLevel = 0;
int osc = 0;
/********************************************************************/
//XBee Stuff
/*
This example is for Series 2 XBee
Receives a ZB RX packet and prints the packet to softserial
*/
XBee xbee = XBee();
XBeeResponse response = XBeeResponse();
// create reusable response objects for responses we expect to handle
ZBRxResponse rx = ZBRxResponse();
ModemStatusResponse msr = ModemStatusResponse();
// Define NewSoftSerial TX/RX pins
// Connect Arduino pin 8 to TX of usb-serial device
uint8_t ssRX = 8;
// Connect Arduino pin 4 to RX of usb-serial device
uint8_t ssTX = 4;
// Remember to connect all devices to a common Ground: XBee, Arduino and USB-Serial device
SoftwareSerial nss(ssRX, ssTX);
//End Xbee Stuff
//Setup
void setup()
{
// initialize the LED/SSR pins as an output:
pinMode(offPin, OUTPUT);
pinMode(pw1Pin, OUTPUT);
pinMode(pw2Pin, OUTPUT);
pinMode(pw3Pin, OUTPUT);
pinMode(oscPin, OUTPUT);
// initialize the pushbutton pins as an input:
//to do: add timer button.
pinMode(pwrButtonPin, INPUT_PULLUP);
pinMode (oscButtonPin, INPUT_PULLUP);
//
// start serial port
Serial.begin(9600);
Serial.println("Starting...");
// Start DS1820B
sensors.begin();
readTemperature();
//set power to off
digitalWrite(offPin, HIGH);
digitalWrite(pw1Pin, LOW);
digitalWrite(pw2Pin, LOW);
digitalWrite(pw3Pin, LOW);
//set oscillation off
digitalWrite(oscPin, LOW);
//
//Xbee Setup
xbee.setSerial(Serial);
nss.begin(9600);
//this does not print to the console of the recieving XBee
nss.println("Starting up!");
//
}
/********************************************************************/
//Loop
void loop()
{
/*******************************************************************
//XBEE.... Commented out because it doesn't do anything.
//this was copy/pasted from the link provided above.
xbee.readPacket();
if (xbee.getResponse().isAvailable()) {
// got something
if (xbee.getResponse().getApiId() == ZB_RX_RESPONSE) {
// got a zb rx packet
// now fill our zb rx class
xbee.getResponse().getZBRxResponse(rx);
nss.println("Got an rx packet!");
if (rx.getOption() == ZB_PACKET_ACKNOWLEDGED) {
// the sender got an ACK
nss.println("packet acknowledged");
} else {
nss.println("packet not acknowledged");
}
nss.print("checksum is ");
nss.println(rx.getChecksum(), HEX);
nss.print("packet length is ");
nss.println(rx.getPacketLength(), DEC);
for (int i = 0; i < rx.getDataLength(); i++) {
nss.print("payload [");
nss.print(i, DEC);
nss.print("] is ");
nss.println(rx.getData()[i], HEX);
}
for (int i = 0; i < xbee.getResponse().getFrameDataLength(); i++) {
nss.print("frame data [");
nss.print(i, DEC);
nss.print("] is ");
nss.println(xbee.getResponse().getFrameData()[i], HEX);
}
}
} else if (xbee.getResponse().isError()) {
nss.print("error code:");
nss.println(xbee.getResponse().getErrorCode());
}
// End XBee stuff
*******************************************************************/
// read the state of the power button value:
pwrButtonState = digitalRead(pwrButtonPin);
// check if the pushbutton is pressed. If it is, the buttonState is LOW:
if (pwrButtonState == LOW) {
// run powerbutton:
powerButton();
}
/********************************************************************/
// read the state of the oscillate button:
oscButtonState = digitalRead(oscButtonPin);
// check if the button is pressed. If it is, the buttonState is LOW:
if (oscButtonState == LOW) {
// osc button:
oscButton();
}
/********************************************************************/
//Read temperature:
if (cycles == 500) {
cycles = 0;
readTemperature();
}
//increment cycle count
cycles = (cycles+1);
delay(100);
}
/********************************************************************/
//Power Button press
void powerButton()
{
if (powerLevel == 0)
{
//set level to 1, turn on level 1 relay
powerLevel = 1;
digitalWrite(offPin, LOW);
digitalWrite(pw1Pin, HIGH);
digitalWrite(pw2Pin, LOW);
digitalWrite(pw3Pin, LOW);
Serial.println("Power Level 1");
}
else if (powerLevel == 1)
{
//
powerLevel = 2;
digitalWrite(offPin, LOW);
digitalWrite(pw1Pin, HIGH);
digitalWrite(pw2Pin, HIGH);
digitalWrite(pw3Pin, LOW);
Serial.println("Power Level 2");
}
else if (powerLevel == 2)
{
//
powerLevel = 3;
digitalWrite(offPin, LOW);
digitalWrite(pw1Pin, HIGH);
digitalWrite(pw2Pin, HIGH);
digitalWrite(pw3Pin, HIGH);
Serial.println("Power Level 3");
}
else if (powerLevel == 3)
{
//
powerLevel = 0;
digitalWrite(offPin, HIGH);
digitalWrite(pw1Pin, LOW);
digitalWrite(pw2Pin, LOW);
digitalWrite(pw3Pin, LOW);
Serial.println("Power Off");
}
else
{
powerLevel = 0;
Serial.println("Power Level Error. Set to off");
digitalWrite(offPin, HIGH);
digitalWrite(pw1Pin, LOW);
digitalWrite(pw2Pin, LOW);
digitalWrite(pw3Pin, LOW);
}
delay(100);
}
/********************************************************************/
//oscillate button press
void oscButton ()
{
//if off, switch on
if (osc == 0)
{
//set level to 1, turn on level 1 relay
osc = 1;
digitalWrite(oscPin, HIGH);
Serial.println("oscillation on");
}
//if on, switch off
else if (osc == 1)
{
//
osc = 0;
digitalWrite(oscPin, LOW);
Serial.println("oscillation off");
}
//unexpected state correction. set to 0 if not 0 or 1
else
{
//
osc = 0;
digitalWrite(oscPin, LOW);
Serial.println("oscillation setting error");
}
delay (100);
}
/********************************************************************/
void timerButton()
{
//To Do...
}
/********************************************************************/
void readTemperature()
{
sensors.requestTemperatures(); // Send the command to get temperature readings
//print results to serial
Serial.println("Temperature is: ");
Serial.println(sensors.getTempCByIndex(0)); // 0=first sensor on 1wire bus
}
So, I’d very much appreciate any pointers at all for doing the following:
- Connecting this device to HA using ZHA
- Control of the 3 relays via ZHA to control the power level of the fan.
- Control the fan oscillation, via ZHA
- Use the DS18B20 as a temperature sensor via ZHA
Thanks